diff --git a/README.md b/README.md index 2836596..f23eb80 100644 --- a/README.md +++ b/README.md @@ -495,7 +495,7 @@ struct drawable { private: using Storage = dyno::sbo_storage<16>; using VTable = dyno::vtable< - dyno::local>, + dyno::local>, dyno::remote >; dyno::poly poly_; diff --git a/benchmark/any_iterator/dyno_generic.hpp b/benchmark/any_iterator/dyno_generic.hpp index 23bb0c5..43545e5 100644 --- a/benchmark/any_iterator/dyno_generic.hpp +++ b/benchmark/any_iterator/dyno_generic.hpp @@ -66,9 +66,7 @@ namespace dyno_generic { int, dyno::local_storage<16>, dyno::vtable< - dyno::local>, + dyno::local>, dyno::remote > >; diff --git a/benchmark/vtable/dispatch.2.cpp b/benchmark/vtable/dispatch.2.cpp index 6a7fb15..a0d9178 100644 --- a/benchmark/vtable/dispatch.2.cpp +++ b/benchmark/vtable/dispatch.2.cpp @@ -27,7 +27,7 @@ static void BM_dispatch2(benchmark::State& state) { } } -template +template using inline_only = dyno::vtable< dyno::local>, dyno::remote @@ -36,6 +36,6 @@ using inline_only = dyno::vtable< static constexpr int N = 100; BENCHMARK_TEMPLATE(BM_dispatch2, inheritance_tag)->Arg(N); BENCHMARK_TEMPLATE(BM_dispatch2, inline_only<>)->Arg(N); -BENCHMARK_TEMPLATE(BM_dispatch2, inline_only)->Arg(N); -BENCHMARK_TEMPLATE(BM_dispatch2, inline_only)->Arg(N); +BENCHMARK_TEMPLATE(BM_dispatch2, inline_only<"f1"_s>)->Arg(N); +BENCHMARK_TEMPLATE(BM_dispatch2, inline_only<"f1"_s, "f2"_s>)->Arg(N); BENCHMARK_MAIN(); diff --git a/benchmark/vtable/dispatch.3.cpp b/benchmark/vtable/dispatch.3.cpp index 8c5b7dd..55d8a22 100644 --- a/benchmark/vtable/dispatch.3.cpp +++ b/benchmark/vtable/dispatch.3.cpp @@ -28,7 +28,7 @@ static void BM_dispatch3(benchmark::State& state) { } } -template +template using inline_only = dyno::vtable< dyno::local>, dyno::remote @@ -37,7 +37,7 @@ using inline_only = dyno::vtable< static constexpr int N = 100; BENCHMARK_TEMPLATE(BM_dispatch3, inheritance_tag)->Arg(N); BENCHMARK_TEMPLATE(BM_dispatch3, inline_only<>)->Arg(N); -BENCHMARK_TEMPLATE(BM_dispatch3, inline_only)->Arg(N); -BENCHMARK_TEMPLATE(BM_dispatch3, inline_only)->Arg(N); -BENCHMARK_TEMPLATE(BM_dispatch3, inline_only)->Arg(N); +BENCHMARK_TEMPLATE(BM_dispatch3, inline_only<"f1"_s>)->Arg(N); +BENCHMARK_TEMPLATE(BM_dispatch3, inline_only<"f1"_s, "f2"_s>)->Arg(N); +BENCHMARK_TEMPLATE(BM_dispatch3, inline_only<"f1"_s, "f2"_s, "f3"_s>)->Arg(N); BENCHMARK_MAIN(); diff --git a/benchmark/vtable/dispatch.4.cpp b/benchmark/vtable/dispatch.4.cpp index d3cf7d3..7d926cf 100644 --- a/benchmark/vtable/dispatch.4.cpp +++ b/benchmark/vtable/dispatch.4.cpp @@ -29,7 +29,7 @@ static void BM_dispatch4(benchmark::State& state) { } } -template +template using inline_only = dyno::vtable< dyno::local>, dyno::remote @@ -38,8 +38,8 @@ using inline_only = dyno::vtable< static constexpr int N = 100; BENCHMARK_TEMPLATE(BM_dispatch4, inheritance_tag)->Arg(N); BENCHMARK_TEMPLATE(BM_dispatch4, inline_only<>)->Arg(N); -BENCHMARK_TEMPLATE(BM_dispatch4, inline_only)->Arg(N); -BENCHMARK_TEMPLATE(BM_dispatch4, inline_only)->Arg(N); -BENCHMARK_TEMPLATE(BM_dispatch4, inline_only)->Arg(N); -BENCHMARK_TEMPLATE(BM_dispatch4, inline_only)->Arg(N); +BENCHMARK_TEMPLATE(BM_dispatch4, inline_only<"f1"_s>)->Arg(N); +BENCHMARK_TEMPLATE(BM_dispatch4, inline_only<"f1"_s, "f2"_s>)->Arg(N); +BENCHMARK_TEMPLATE(BM_dispatch4, inline_only<"f1"_s, "f2"_s, "f3"_s>)->Arg(N); +BENCHMARK_TEMPLATE(BM_dispatch4, inline_only<"f1"_s, "f2"_s, "f3"_s, "f4"_s>)->Arg(N); BENCHMARK_MAIN(); diff --git a/example/vtable_traits.cpp b/example/vtable_traits.cpp index 1a7b026..f0f61c1 100644 --- a/example/vtable_traits.cpp +++ b/example/vtable_traits.cpp @@ -59,9 +59,7 @@ struct any_iterator { using Concept = Iterator; using Storage = dyno::remote_storage; using VTable = dyno::vtable< - dyno::local>, + dyno::local>, dyno::remote >; dyno::poly poly_; diff --git a/include/dyno/detail/dsl.hpp b/include/dyno/detail/dsl.hpp index 664fa92..f1b2670 100644 --- a/include/dyno/detail/dsl.hpp +++ b/include/dyno/detail/dsl.hpp @@ -104,6 +104,9 @@ namespace detail { return detail::delayed_call{std::forward(args)...}; } + static constexpr char storage_[] = {c..., '\0'}; + constexpr operator char const*() const { return storage_; } + using hana_tag = typename boost::hana::tag_of>::type; }; @@ -115,6 +118,21 @@ namespace detail { constexpr auto prepare_string(S) { return detail::prepare_string_impl(std::make_index_sequence{}); } + + constexpr std::size_t constexpr_strlen(char const* s) { + std::size_t len = 0; + while (*s++ != '\0') ++len; + return len; + } + + template + constexpr auto make_string() { + struct tmp { + static constexpr std::size_t size() { return detail::constexpr_strlen(s); } + static constexpr char const* get() { return s; } + }; + return detail::prepare_string(tmp{}); + } } // end namespace detail inline namespace literals { diff --git a/include/dyno/vtable.hpp b/include/dyno/vtable.hpp index 2d6951f..32b3aa7 100644 --- a/include/dyno/vtable.hpp +++ b/include/dyno/vtable.hpp @@ -6,6 +6,7 @@ #define DYNO_VTABLE_HPP #include +#include #include #include @@ -208,11 +209,11 @@ struct joined_vtable { ////////////////////////////////////////////////////////////////////////////// // Selectors -template +template struct only { template constexpr auto operator()(All all) const { - auto matched = boost::hana::make_set(Functions{}...); + auto matched = boost::hana::make_set(detail::make_string()...); static_assert(decltype(boost::hana::is_subset(matched, all))::value, "dyno::only: Some functions specified in this selector are not part of " "the concept to which the selector was applied."); @@ -223,11 +224,11 @@ struct only { } }; -template +template struct except { template constexpr auto operator()(All all) const { - auto not_matched = boost::hana::make_set(Functions{}...); + auto not_matched = boost::hana::make_set(detail::make_string()...); static_assert(decltype(boost::hana::is_subset(not_matched, all))::value, "dyno::except: Some functions specified in this selector are not part of " "the concept to which the selector was applied."); @@ -251,12 +252,12 @@ namespace detail { template struct is_valid_selector : boost::hana::false_ { }; - template + template struct is_valid_selector> : boost::hana::true_ { }; - template + template struct is_valid_selector> : boost::hana::true_ { }; @@ -389,12 +390,12 @@ constexpr auto generate_vtable(Policies policies) { // cumbersome. Selectors provided by the library are: // // dyno::only -// Picks only the specified functions from a concept. `functions` must be -// compile-time strings, such as `dyno::only`. +// Picks only the specified functions from a concept. `functions...` must +// be compile-time strings, such as `dyno::only<"foo"_s, "bar"_s>`. // // dyno::except -// Picks all but the specified functions from a concept. `functions` must -// be compile-time strings, such as `dyno::except`. +// Picks all but the specified functions from a concept. `functions...` +// must be compile-time strings, such as `dyno::except<"foo"_s, "bar"_s>`. // // dyno::everything // Picks all the functions from a concept. diff --git a/test/detail/dsl.make_string.cpp b/test/detail/dsl.make_string.cpp new file mode 100644 index 0000000..aeca6a9 --- /dev/null +++ b/test/detail/dsl.make_string.cpp @@ -0,0 +1,28 @@ +// Copyright Louis Dionne 2017 +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + +#include + +#include + + +int main() { + { + static constexpr char const s[] = ""; + static_assert(std::is_same()), + dyno::detail::string<>>{}); + } + + { + static constexpr char const s[] = "a"; + static_assert(std::is_same()), + dyno::detail::string<'a'>>{}); + } + + { + static constexpr char const s[] = "abc"; + static_assert(std::is_same()), + dyno::detail::string<'a', 'b', 'c'>>{}); + } +} diff --git a/test/vtable.fail.1.cpp b/test/vtable.fail.1.cpp index ea1e7d6..1826e7f 100644 --- a/test/vtable.fail.1.cpp +++ b/test/vtable.fail.1.cpp @@ -21,8 +21,8 @@ auto dyno::concept_map = dyno::make_concept_map( int main() { using VTable = dyno::vtable< - dyno::local>, - dyno::remote> + dyno::local>, + dyno::remote> >; VTable::apply vtable{ dyno::complete_concept_map(dyno::concept_map) diff --git a/test/vtable.fail.3.cpp b/test/vtable.fail.3.cpp index 04555bf..f50de6e 100644 --- a/test/vtable.fail.3.cpp +++ b/test/vtable.fail.3.cpp @@ -25,5 +25,5 @@ int main() { auto complete = dyno::complete_concept_map(dyno::concept_map); // MESSAGE[The policies specified in the vtable did not fully cover all the functions provided by the concept] - dyno::vtable>>::apply vtable{complete}; + dyno::vtable>>::apply vtable{complete}; } diff --git a/test/vtable.fail.4.cpp b/test/vtable.fail.4.cpp index 4a29d66..05a1d6e 100644 --- a/test/vtable.fail.4.cpp +++ b/test/vtable.fail.4.cpp @@ -24,7 +24,7 @@ int main() { // MESSAGE[Some functions specified in this selector are not part of the concept to which the selector was applied] dyno::vtable< - dyno::local>, + dyno::local>, dyno::remote >::apply vtable{complete}; } diff --git a/test/vtable.fail.5.cpp b/test/vtable.fail.5.cpp index ce52d04..2337789 100644 --- a/test/vtable.fail.5.cpp +++ b/test/vtable.fail.5.cpp @@ -24,7 +24,7 @@ int main() { // MESSAGE[Some functions specified in this selector are not part of the concept to which the selector was applied] dyno::vtable< - dyno::local>, + dyno::local>, dyno::remote >::apply vtable{complete}; } diff --git a/test/vtable.selector.fail.2.cpp b/test/vtable.selector.fail.2.cpp index 3c29e72..ec70e52 100644 --- a/test/vtable.selector.fail.2.cpp +++ b/test/vtable.selector.fail.2.cpp @@ -24,7 +24,7 @@ int main() { // MESSAGE[dyno::remote: Provided invalid selector. Valid selectors are] dyno::vtable< - dyno::local>, + dyno::local>, dyno::remote >::apply vtable{complete}; }