Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions doc/mp11/utility.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,40 @@ using R1 = mp_transform_q<mp_quote_trait<std::add_pointer>, L1>;
// mp_list<int*, void*, float*>
```

## mp_quote_expr<Expr>

template<auto Expr>
struct mp_quote_expr {
template<class... Ts>
using fn = decltype(Expr(std::declval<Ts&>()...));
};

`mp_quote_expr<Expr>` transforms the template `Expr` into a _quoted metafunction_, a type with a nested template `fn` such that `fn<T...>` returns `Expr(std::declval<Ts&>()...)`.

.Using mp_quote_expr to wrap types depending on whether they have a `value` or not
```
template<class> struct with_value {};
template<class> struct without_value {};

struct foo { int value{}; };
struct bar { };

using L1 = mp_list<foo, bar>;
using R1 = mp_transform_q<
mp_quote_expr<[]<class T>(T t) {
if constexpr (requires { t.value; }) {
return with_value<T>{};
} else {
return without_value<T>{};
}
}>,
L1
>;
// mp_list<with_value<foo>, without_value<bar>>
```

> `mp_quote_trait<F>` requires C++20 support

## mp_invoke_q<Q, T...>

template<class Q, class... T> using mp_invoke_q = typename Q::template fn<T...>;
Expand Down
12 changes: 12 additions & 0 deletions include/boost/mp11/detail/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,18 @@
# define BOOST_MP11_HAS_FOLD_EXPRESSIONS
#endif

// BOOST_MP11_HAS_NONTYPE_TEMPLATE_ARGS

#if !defined(BOOST_MP11_HAS_NONTYPE_TEMPLATE_ARGS) && defined(__cpp_nontype_template_args) && __cpp_nontype_template_args >= 201911
# define BOOST_MP11_HAS_NONTYPE_TEMPLATE_ARGS
#endif

// BOOST_MP11_HAS_NONTYPE_TEMPLATE_PARAMETER_AUTO

#if !defined(BOOST_MP11_HAS_NONTYPE_TEMPLATE_PARAMETER_AUTO) && defined(__cpp_nontype_template_parameter_auto) && __cpp_nontype_template_parameter_auto >= 201606
# define BOOST_MP11_HAS_NONTYPE_TEMPLATE_PARAMETER_AUTO
#endif

// BOOST_MP11_HAS_TYPE_PACK_ELEMENT

#if defined(__has_builtin)
Expand Down
8 changes: 8 additions & 0 deletions include/boost/mp11/utility.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,14 @@ template<class... Q> struct mp_compose_q
template<class T> using fn = mp_fold<mp_list<Q...>, T, detail::mp_reverse_invoke_q>;
};

#if defined(BOOST_MP11_HAS_NONTYPE_TEMPLATE_ARGS) && defined(BOOST_MP11_HAS_NONTYPE_TEMPLATE_PARAMETER_AUTO)
template<auto Expr>
struct mp_quote_expr {
template<class... Ts>
using fn = decltype(Expr(std::declval<Ts&>()...));
};
#endif

} // namespace mp11
} // namespace boost

Expand Down
1 change: 1 addition & 0 deletions test/Jamfile
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ run mp_defer.cpp ;
run mp_quote.cpp ;
run mp_invoke_q.cpp ;
run mp_invoke_q_sf.cpp ;
run mp_quote_expr.cpp ;
run mp_quote_trait.cpp ;
run mp_cond.cpp ;
run mp_cond_sf.cpp ;
Expand Down
69 changes: 69 additions & 0 deletions test/mp_quote_expr.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@

// Copyright 2021 Kris Jusiak.
//
// Distributed under the Boost Software License, Version 1.0.
//
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt

#include <boost/mp11/utility.hpp>
#include <boost/mp11/algorithm.hpp>
#include <boost/mp11/list.hpp>
#include <boost/core/lightweight_test_trait.hpp>

int main()
{
#if defined(BOOST_MP11_HAS_NONTYPE_TEMPLATE_ARGS) && defined(BOOST_MP11_HAS_NONTYPE_TEMPLATE_PARAMETER_AUTO)
using boost::mp11::mp_list;
using boost::mp11::mp_transform_q;
using boost::mp11::mp_quote_expr;

constexpr auto expr = [](auto t) { return t; };

{
BOOST_TEST_TRAIT_TRUE((std::is_same<
mp_list<>,
mp_transform_q<
mp_quote_expr<expr>,
mp_list<>
>
>));
}

{
BOOST_TEST_TRAIT_TRUE((std::is_same<
mp_list<int>,
mp_transform_q<
mp_quote_expr<expr>,
mp_list<int>
>
>));
}

struct a{};
struct b{};

{
BOOST_TEST_TRAIT_TRUE((std::is_same<
mp_list<a, b>,
mp_transform_q<
mp_quote_expr<expr>,
mp_list<a, b>
>
>));
}

{
constexpr auto to_ptr = [](auto& t) { return &t; };

BOOST_TEST_TRAIT_TRUE((std::is_same<
mp_list<a*, b*>,
mp_transform_q<
mp_quote_expr<to_ptr>,
mp_list<a, b>
>
>));
}
#endif
return boost::report_errors();
}