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
69 changes: 65 additions & 4 deletions include/meta/meta.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
#include <type_traits>
#include <utility>

#ifdef META_CXX_VISIT
#include <array>
#endif

#ifdef __clang__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
Expand Down Expand Up @@ -2825,8 +2829,8 @@ namespace meta
/// \endcond

#if META_CXX_INLINE_VARIABLES
/// `for_each(L, Fn)` calls the \p Fn for each
/// argument in the \p L.
/// `for_each(list, fn)` calls the unary function \p fn for each
/// argument in the `meta::List` \p list.
/// \ingroup runtime
inline constexpr detail::for_each_fn for_each{};
#else
Expand All @@ -2835,8 +2839,8 @@ namespace meta
{
/// \endcond

/// `for_each(List, UnaryFunction)` calls the \p UnaryFunction for each
/// argument in the \p List.
/// `for_each(list, fn)` calls the unary function \p fn for each
/// argument in the `meta::List` \p list.
/// \ingroup runtime
constexpr auto &&for_each = detail::static_const<detail::for_each_fn>::value;

Expand All @@ -2845,6 +2849,63 @@ namespace meta
/// \endcond
#endif

#if META_CXX_VISIT
///////////////////////////////////////////////////////////////////////////////////////////
// visit
/// \cond
namespace detail
{

struct visit_fn
{
template<typename Fn, typename Type>
struct visit{
static constexpr void call(Fn f){ f(Type{}); }
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to use this struct dispatch to defer no to have void as Type instantiate
in FnPtr.

};

template<typename Fn>
using FnPtr = decltype(&visit<Fn, void>::call);

template<typename Fn, typename... Types>
static constexpr auto make_fn_map(list<Types...>) -> std::array<FnPtr<Fn>, sizeof...(Types)>
{
return {&visit<Fn, Types>::call...};
}

template <class Fn, class... Args>
constexpr auto operator()(list<Args...> l, std::size_t i, Fn&& f) const -> Fn
{
using F = decltype(std::forward<Fn>(f));
constexpr auto map = make_fn_map<F>(l);
if(i < map.size()) map[i](std::forward<Fn>(f));
return f;
}
};
} // namespace detail
/// \endcond

#if META_CXX_INLINE_VARIABLES
/// `visit(list, i, fn)` calls the unary function \p fn for the \p i
/// -th argument in the `meta::List` \p list. No-op if \p i is out-of-range.
/// \ingroup runtime
inline constexpr detail::visit_fn visit{};
#else
///\cond
namespace
{
/// \endcond

/// `visit(list, i, fn)` calls the unary function \p fn for the \p i
/// -th argument in the `meta::List` \p list. No-op if \p i is out-of-range.
/// \ingroup runtime
constexpr auto &&visit = detail::static_const<detail::visit_fn>::value;

/// \cond
}
/// \endcond
#endif
#endif

///////////////////////////////////////////////////////////////////////////////////////////
// transpose
/// Given a list of lists of the same number of types \p ListOfLists, transpose the
Expand Down
4 changes: 4 additions & 0 deletions include/meta/meta_fwd.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,10 @@
#endif
#endif

#ifndef META_CXX_VISIT
#define META_CXX_VISIT (META_CXX_VER >= META_CXX_STD_17)
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need full c++17 support -> constexpr everywhere...

#endif

#if defined(__cpp_concepts) && __cpp_concepts > 0
#if !META_CXX_VARIABLE_TEMPLATES
#error Concepts, but no variable templates?
Expand Down
7 changes: 6 additions & 1 deletion test/meta.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1571,7 +1571,12 @@ namespace test_meta_group
constexpr auto r = meta::for_each(runtime_list{}, detail::check_integral());
static_assert(
std::is_same<_t<std::remove_cv<decltype(r)>>, detail::check_integral>::value, "");
} // namespace test_runtime_group
#if META_CXX_VISIT
constexpr auto r2 = meta::visit(l{}, 2, check_integral());
static_assert(
std::is_same<meta::_t<std::remove_cv<decltype(r)>>, check_integral>::value, "");
#endif
} // namespace test_runtime_group

} // namespace test_algorithm_group

Expand Down