Skip to content

Commit

Permalink
🆕 Add mp_quote_expr to quote with lambda expressions
Browse files Browse the repository at this point in the history
Problem:
- There is no easy way to quote metafunction directly with lambda expressions.

Solution:
- Add mp_quote_expr.

Note:
- mp_quote_expr requires C++20.
  • Loading branch information
kris-jusiak committed Jun 13, 2021
1 parent 20aa0f9 commit 98605ce
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 0 deletions.
29 changes: 29 additions & 0 deletions doc/mp11/utility.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,35 @@ 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 find out struct with a value member
```
struct foo { int value{}; };
struct bar { };

using L1 = mp_list<int, foo, bar>;
using R1 = mp_transform_q<
mp_quote_expr<[](auto t) {
if constexpr (requires { t.value; }) {
return t;
}
}>,
L1
>;
// mp_list<void, foo, void>
```

> `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
6 changes: 6 additions & 0 deletions include/boost/mp11/detail/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,12 @@
# define BOOST_MP11_HAS_FOLD_EXPRESSIONS
#endif

// BOOST_MP11_HAS_NONTYPE_TEMPLATE

#if !defined(BOOST_MP11_HAS_NONTYPE_TEMPLATE) && defined(__cpp_nontype_template_args) && defined(__cpp_nontype_template_parameter_auto) && __cplusplus >= 202002L && !BOOST_MP11_WORKAROUND( BOOST_MP11_CLANG, < 120 )
# define BOOST_MP11_HAS_NONTYPE_TEMPLATE
#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)
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
70 changes: 70 additions & 0 deletions test/mp_quote_expr.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@

// 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)
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();
}

0 comments on commit 98605ce

Please sign in to comment.