diff --git a/doc/mp11/examples.adoc b/doc/mp11/examples.adoc index 858bd55..61dac8a 100644 --- a/doc/mp11/examples.adoc +++ b/doc/mp11/examples.adoc @@ -410,21 +410,28 @@ We'll first define a helper quoted metafunction `Qret` that returns the resul decltype( std::declval()( std::declval()... ) ); }; -(Unfortunately, we can't just define this metafunction inside `rvisit`; the language prohibits defining template aliases inside functions.) +Unfortunately, we can't just define this metafunction inside `rvisit`; the language prohibits defining template aliases inside functions. +But we can make use of another C++17 feature for an alternative which can be defined inside and simplifies the implementation further: + + using Qret_F = mp_bind_front; With `Qret` in hand, a `variant` of the possible return types is just a matter of applying it over the possible combinations of the variant values: - using R = mp_product_q, std::remove_reference_t...>; + using R = mp_product_q, std::decay_t...>; + // or + using R = mp_product_q...>; Why does this work? `mp_product, L2, ..., Ln>` returns `L1, ...>`, where `Ui` traverse all possible combinations of list values. Since in our case all `Li` are `std::variant`, the result will also be `std::variant`. (`mp_product_q` is -the same as `mp_product`, but for quoted metafunctions such as our `Qret`.) +the same as `mp_product`, but for quoted metafunctions such as our `Qret` or `Qret_F`.) We needed to use `std::decay_t` for precisely the +same reason as in the link:#fixing-tuple_cat[Fixing tuple_cat example], where `std::decay_t` is an equivalent alternative to `remove_cv_ref`. + One more step remains. Suppose that, as above, we're passing two variants of type `std::variant` and `F` is `[]( auto const& x, auto const& y ){ return x + y; }`. This will generate `R` of length 9, one per each combination, but many of those elements will be the same, either `int` or `float`, and we need to filter out the duplicates. So, we pass the result to `mp_unique`: - using R = mp_unique, std::remove_reference_t...>>; + using R = mp_unique...>>; and we're done: @@ -438,15 +445,11 @@ and we're done: using namespace boost::mp11; -template struct Qret -{ - template using fn = - decltype( std::declval()( std::declval()... ) ); -}; template auto rvisit( F&& f, V&&... v ) { - using R = mp_unique, std::remove_reference_t...>>; + using Qret_F = mp_bind_front; + using R = mp_unique...>>; return std::visit( [&]( auto&&... x ) { return R( std::forward(f)( std::forward(x)... ) ); },