forked from boostorg/mp11
Feature/lambda (#96)
* added mp_lambda * launched GHA * skipped ICE-generating test in GCC < 4.9 * fixed GCC detection in workaround * test-skipped and documented GCC 4.8 bug * added missing s/const/CONST * tempirarily expanded macro to isolate problem with VS2017 * tried workaround for C3546 * tried another workaround * wrapped workaround up * dropped unnecessary devoiding in variadic (member) functions * temporary code to check VS compliance wrt function qualifiers * removed version printer * checked compliance with qualified (member) function partial specialization * checked each partial specialization individually * wrapped up VS2013 investigation * left variadics out of VS2013 * skipped noexcept-involving tests for VS2013 (keyword not supported) * given up on VS2013 support for mp_lambda * dropped lambda_devoid_args
This commit is contained in:
195
include/boost/mp11/lambda.hpp
Normal file
195
include/boost/mp11/lambda.hpp
Normal file
@@ -0,0 +1,195 @@
|
||||
#ifndef BOOST_MP11_LAMBDA_HPP_INCLUDED
|
||||
#define BOOST_MP11_LAMBDA_HPP_INCLUDED
|
||||
|
||||
// Copyright 2024 Joaquin M Lopez Munoz.
|
||||
//
|
||||
// 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/detail/config.hpp>
|
||||
|
||||
#if BOOST_MP11_WORKAROUND(BOOST_MP11_MSVC, <= 1800)
|
||||
// mp_lambda not supported due to compiler limitations
|
||||
#else
|
||||
|
||||
#include <boost/mp11/bind.hpp>
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
|
||||
#if defined(_MSC_VER) || defined(__GNUC__)
|
||||
# pragma push_macro( "I" )
|
||||
# undef I
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace mp11
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<class T> struct lambda_impl;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// mp_lambda
|
||||
template<class T> using mp_lambda = typename detail::lambda_impl<T>::type;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// base case (no placeholder replacement)
|
||||
template<class T> struct lambda_impl
|
||||
{
|
||||
template<class... U> using make = T;
|
||||
using type = mp_bind<make>;
|
||||
};
|
||||
|
||||
// placeholders (behave directly as mp_bind expressions)
|
||||
template<std::size_t I> struct lambda_impl<mp_arg<I>>
|
||||
{
|
||||
using type = mp_arg<I>;
|
||||
};
|
||||
|
||||
#define BOOST_MP11_SPECIALIZE_LAMBDA_IMPL(name, compound_type) \
|
||||
template<class T> using lambda_make_##name = compound_type; \
|
||||
\
|
||||
template<class T> struct lambda_impl<compound_type> \
|
||||
{ \
|
||||
using type = mp_bind<lambda_make_##name, mp_lambda<T>>; \
|
||||
};
|
||||
|
||||
// [basic.type.qualifier]
|
||||
BOOST_MP11_SPECIALIZE_LAMBDA_IMPL(const, const T)
|
||||
BOOST_MP11_SPECIALIZE_LAMBDA_IMPL(volatile, volatile T)
|
||||
BOOST_MP11_SPECIALIZE_LAMBDA_IMPL(const_volatile, const volatile T)
|
||||
|
||||
// [dcl.ptr]
|
||||
BOOST_MP11_SPECIALIZE_LAMBDA_IMPL(pointer, T*)
|
||||
|
||||
// [dcl.ref]
|
||||
// GCC < 7 fails with template<class U> using make = U&;
|
||||
template<class T> struct lambda_impl<T&>
|
||||
{
|
||||
template<class U> using make = typename std::add_lvalue_reference<U>::type;
|
||||
using type = mp_bind<make, mp_lambda<T>>;
|
||||
};
|
||||
|
||||
template<class T> struct lambda_impl<T&&>
|
||||
{
|
||||
template<class U> using make = typename std::add_rvalue_reference<U>::type;
|
||||
using type = mp_bind<make, mp_lambda<T>>;
|
||||
};
|
||||
|
||||
// [dcl.array]
|
||||
BOOST_MP11_SPECIALIZE_LAMBDA_IMPL(array, T[])
|
||||
|
||||
#undef BOOST_MP11_SPECIALIZE_LAMBDA_IMPL
|
||||
|
||||
template<class T, std::size_t N> struct lambda_impl<T[N]>
|
||||
{
|
||||
template<class Q> using make = Q[N];
|
||||
using type = mp_bind<make, mp_lambda<T>>;
|
||||
};
|
||||
|
||||
// [dcl.fct], [dcl.mptr] (member functions)
|
||||
#define BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(name, qualifier) \
|
||||
template<class R, class... T> using lambda_make_fct_##name = R(T...) qualifier; \
|
||||
\
|
||||
template<class R, class... T> struct lambda_impl<R(T...) qualifier> \
|
||||
{ \
|
||||
using type = mp_bind< \
|
||||
lambda_make_fct_##name, \
|
||||
mp_lambda<R>, mp_lambda<T>...>; \
|
||||
}; \
|
||||
\
|
||||
template<class R, class... T> using lambda_make_fct_##name##_ellipsis = \
|
||||
R(T..., ...) qualifier; \
|
||||
\
|
||||
template<class R, class... T> struct lambda_impl<R(T..., ...) qualifier> \
|
||||
{ \
|
||||
using type = mp_bind< \
|
||||
lambda_make_fct_##name##_ellipsis, \
|
||||
mp_lambda<R>, mp_lambda<T>...>; \
|
||||
}; \
|
||||
\
|
||||
template<class R, class C, class... T> using lambda_make_mfptr_##name = \
|
||||
R (C::*)(T...) qualifier; \
|
||||
\
|
||||
template<class R, class C, class... T> struct lambda_impl<R (C::*)(T...) qualifier> \
|
||||
{ \
|
||||
using type = mp_bind< \
|
||||
lambda_make_mfptr_##name, \
|
||||
mp_lambda<R>, mp_lambda<C>, mp_lambda<T>...>; \
|
||||
}; \
|
||||
\
|
||||
template<class R, class C, class... T> using lambda_make_mfptr_##name##_ellipsis = \
|
||||
R (C::*)(T..., ...) qualifier; \
|
||||
\
|
||||
template<class R, class C, class... T> struct lambda_impl<R (C::*)(T..., ...) qualifier> \
|
||||
{ \
|
||||
using type = mp_bind< \
|
||||
lambda_make_mfptr_##name##_ellipsis, \
|
||||
mp_lambda<R>, mp_lambda<C>, mp_lambda<T>...>; \
|
||||
};
|
||||
|
||||
#define BOOST_MP11_EMPTY()
|
||||
|
||||
BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(no_qualifier, BOOST_MP11_EMPTY())
|
||||
BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(const, const)
|
||||
BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(volatile, volatile)
|
||||
BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(const_volatile, const volatile)
|
||||
BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(ref, &)
|
||||
BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(const_ref, const&)
|
||||
BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(volatile_ref, volatile&)
|
||||
BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(const_volatile_ref, const volatile&)
|
||||
BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(rvalue_ref, &&)
|
||||
BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(const_rvalue_ref, const&&)
|
||||
BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(volatile_rvalue_ref, volatile&&)
|
||||
BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(const_volatile_rvalue_ref, const volatile&&)
|
||||
|
||||
#if (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L
|
||||
// P0012R1: exception specification as part of the type system
|
||||
BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(noexcept, noexcept)
|
||||
BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(const_noexcept, const noexcept)
|
||||
BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(volatile_noexcept, volatile noexcept)
|
||||
BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(const_volatile_noexcept, const volatile noexcept)
|
||||
BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(ref_noexcept, & noexcept)
|
||||
BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(const_ref_noexcept, const& noexcept)
|
||||
BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(volatile_ref_noexcept, volatile& noexcept)
|
||||
BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(const_volatile_ref_noexcept, const volatile& noexcept)
|
||||
BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(rvalue_ref_noexcept, && noexcept)
|
||||
BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(const_rvalue_ref_noexcept, const&& noexcept)
|
||||
BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(volatile_rvalue_ref_noexcept, volatile&& noexcept)
|
||||
BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(const_volatile_rvalue_ref_noexcept, const volatile&& noexcept)
|
||||
#endif // P0012R1
|
||||
|
||||
#undef BOOST_MP11_EMPTY
|
||||
#undef BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR
|
||||
|
||||
// [dcl.mptr] (data members)
|
||||
template<class T, class C> struct lambda_impl<T (C::*)>
|
||||
{
|
||||
template<class U, class D> using make = U (D::*);
|
||||
using type = mp_bind<make, mp_lambda<T>, mp_lambda<C>>;
|
||||
};
|
||||
|
||||
// template class instantiation
|
||||
template<template <class...> class C, class... Ts> struct lambda_impl<C<Ts...>>
|
||||
{
|
||||
using type = mp_bind<C, mp_lambda<Ts>...>;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace mp11
|
||||
} // namespace boost
|
||||
|
||||
#if defined(_MSC_VER) || defined(__GNUC__)
|
||||
# pragma pop_macro( "I" )
|
||||
#endif
|
||||
|
||||
#endif // mp_lambda supported
|
||||
|
||||
#endif // #ifndef BOOST_MP11_LAMBDA_HPP_INCLUDED
|
||||
Reference in New Issue
Block a user