rename chapters

This commit is contained in:
Amar Mahmutbegovic
2025-02-09 13:11:21 +01:00
parent 8634accda5
commit 526e6ec009
2928 changed files with 0 additions and 0 deletions

View File

@@ -11,7 +11,7 @@ set(CMAKE_SIZE "arm-none-eabi-size")
set(RENODE "renode" CACHE STRING "Path to Renode executable")
set(MAIN_CPP_PATH "${CMAKE_SOURCE_DIR}/app/src/")
set(MAIN_CPP_FILE_NAME "main_fsm_simple.cpp" CACHE STRING "main file")
set(MAIN_CPP_FILE_NAME "main.cpp" CACHE STRING "main file")
list(APPEND LIB_SPECS "-specs=nosys.specs")
list(APPEND LIB_SPECS "-specs=nano.specs")
@@ -85,11 +85,10 @@ include_directories(
${CMAKE_SOURCE_DIR}/app/inc
${CMAKE_SOURCE_DIR}/hal/uart/inc
${CMAKE_SOURCE_DIR}/hal/inc
${CMAKE_SOURCE_DIR}/hal/gpio/inc
${CMAKE_SOURCE_DIR}/hal/adc/inc
${CMAKE_SOURCE_DIR}/cstdlib_support
${CMAKE_SOURCE_DIR}/util/inc
${CMAKE_SOURCE_DIR}/libs/boost
${CMAKE_SOURCE_DIR}/libs
)
set(EXECUTABLE ${PROJECT_NAME}.elf)
@@ -108,8 +107,6 @@ add_executable(
platform/src/stm32f0xx_hal_msp.c
platform/src/stm32f0xx_it.c
platform/src/system_stm32f0xx.c
hal/gpio/src/gpio.cpp
hal/gpio/src/gpio_interrupt_manager.cpp
hal/adc/src/adc_stm32.cpp
cstdlib_support/retarget.cpp
util/src/units.cpp
@@ -118,6 +115,8 @@ add_executable(
target_link_libraries(${EXECUTABLE} PUBLIC)
target_compile_definitions(${EXECUTABLE} PUBLIC "-DSIMULATE_FREESTANDING")
target_include_directories(${EXECUTABLE} PUBLIC ${PROJECT_BINARY_DIR}
${CMAKE_SOURCE_DIR})
@@ -131,6 +130,8 @@ target_link_options(
-mthumb
${LIB_SPECS}
-lnosys
-u
_printf_float
-lc
-lm
-Wl,--no-warn-rwx-segments

View File

@@ -0,0 +1,119 @@
#include <algorithm>
#include <cstdint>
#include <cstdio>
#include <functional>
#include <stm32f072xb.h>
#include <hal.hpp>
#include <stm32f0xx_hal_uart.hpp>
#include <uart_stm32.hpp>
#include <retarget.hpp>
#include <cassert>
#include <cib/cib.hpp>
struct runtime_init : public flow::service<> {};
struct main_loop : public callback::service<> {};
struct send_temperature : public callback::service<float> {};
struct i2c {
constexpr static auto init = flow::action<"i2c_init">(
[](){
printf("I2C init ...\r\n");
});
constexpr static auto config = cib::config(
cib::extend<runtime_init>(*init)
);
};
struct temperature_sensor_component {
constexpr static auto init = flow::action<"temp_sensor_init">(
[]() {
printf("Initializing temperature sensor ... \r\n");
});
constexpr static auto read_temperature = []() {
float temperature = 23.4f;
cib::service<send_temperature>(temperature);
};
constexpr static auto config = cib::config(
cib::extend<main_loop>(read_temperature),
cib::extend<runtime_init>(i2c::init >> *init)
);
};
struct display_temperature_component {
constexpr static auto display_temperature = [](float temperature) {
printf("Temperature is %.2f C\r\n", temperature);
};
constexpr static auto config = cib::config(
cib::extend<send_temperature>(display_temperature)
);
};
struct data_sender_component {
constexpr static auto send_temp = [](float temp) {
printf("Sending temperature %.2f C\r\n", temp);
};
constexpr static auto config = cib::config(
cib::extend<send_temperature>(send_temp)
);
};
struct my_project {
constexpr static auto config = cib::config(
cib::exports<runtime_init,
main_loop,
send_temperature>,
cib::components<i2c,
temperature_sensor_component,
display_temperature_component,
data_sender_component>
);
};
int main()
{
hal::init();
hal::uart_stm32<hal::stm32::uart> uart(USART2);
uart.init();
retarget::set_stdio_uart(&uart);
cib::nexus<my_project> nexus{};
nexus.init();
nexus.service<runtime_init>();
for(int i = 0; i < 3; i++)
{
nexus.service<main_loop>();
}
while(true)
{
}
}

View File

@@ -0,0 +1,22 @@
#ifndef BOOST_MP11_HPP_INCLUDED
#define BOOST_MP11_HPP_INCLUDED
// Copyright 2015 Peter Dimov.
//
// 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/list.hpp>
#include <boost/mp11/algorithm.hpp>
#include <boost/mp11/integral.hpp>
#include <boost/mp11/utility.hpp>
#include <boost/mp11/function.hpp>
#include <boost/mp11/map.hpp>
#include <boost/mp11/set.hpp>
#include <boost/mp11/bind.hpp>
#include <boost/mp11/integer_sequence.hpp>
#include <boost/mp11/tuple.hpp>
#endif // #ifndef BOOST_MP11_HPP_INCLUDED

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,111 @@
#ifndef BOOST_MP11_BIND_HPP_INCLUDED
#define BOOST_MP11_BIND_HPP_INCLUDED
// Copyright 2017, 2018 Peter Dimov.
//
// 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/algorithm.hpp>
#include <boost/mp11/utility.hpp>
#include <cstddef>
namespace boost
{
namespace mp11
{
// mp_bind_front
template<template<class...> class F, class... T> struct mp_bind_front
{
// the indirection through mp_defer works around the language inability
// to expand U... into a fixed parameter list of an alias template
template<class... U> using fn = typename mp_defer<F, T..., U...>::type;
};
template<class Q, class... T> using mp_bind_front_q = mp_bind_front<Q::template fn, T...>;
// mp_bind_back
template<template<class...> class F, class... T> struct mp_bind_back
{
template<class... U> using fn = typename mp_defer<F, U..., T...>::type;
};
template<class Q, class... T> using mp_bind_back_q = mp_bind_back<Q::template fn, T...>;
// mp_arg
template<std::size_t I> struct mp_arg
{
template<class... T> using fn = mp_at_c<mp_list<T...>, I>;
};
using _1 = mp_arg<0>;
using _2 = mp_arg<1>;
using _3 = mp_arg<2>;
using _4 = mp_arg<3>;
using _5 = mp_arg<4>;
using _6 = mp_arg<5>;
using _7 = mp_arg<6>;
using _8 = mp_arg<7>;
using _9 = mp_arg<8>;
// mp_bind
template<template<class...> class F, class... T> struct mp_bind;
namespace detail
{
template<class V, class... T> struct eval_bound_arg
{
using type = V;
};
template<std::size_t I, class... T> struct eval_bound_arg<mp_arg<I>, T...>
{
using type = typename mp_arg<I>::template fn<T...>;
};
template<template<class...> class F, class... U, class... T> struct eval_bound_arg<mp_bind<F, U...>, T...>
{
using type = typename mp_bind<F, U...>::template fn<T...>;
};
template<template<class...> class F, class... U, class... T> struct eval_bound_arg<mp_bind_front<F, U...>, T...>
{
using type = typename mp_bind_front<F, U...>::template fn<T...>;
};
template<template<class...> class F, class... U, class... T> struct eval_bound_arg<mp_bind_back<F, U...>, T...>
{
using type = typename mp_bind_back<F, U...>::template fn<T...>;
};
} // namespace detail
template<template<class...> class F, class... T> struct mp_bind
{
#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, == 1915 )
private:
template<class... U> struct _f { using type = F<typename detail::eval_bound_arg<T, U...>::type...>; };
public:
template<class... U> using fn = typename _f<U...>::type;
#else
template<class... U> using fn = F<typename detail::eval_bound_arg<T, U...>::type...>;
#endif
};
template<class Q, class... T> using mp_bind_q = mp_bind<Q::template fn, T...>;
} // namespace mp11
} // namespace boost
#endif // #ifndef BOOST_MP11_BIND_HPP_INCLUDED

View File

@@ -0,0 +1,149 @@
#ifndef BOOST_MP11_DETAIL_CONFIG_HPP_INCLUDED
#define BOOST_MP11_DETAIL_CONFIG_HPP_INCLUDED
// Copyright 2016, 2018, 2019 Peter Dimov.
//
// 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
// BOOST_MP11_WORKAROUND
#if defined( BOOST_STRICT_CONFIG ) || defined( BOOST_MP11_NO_WORKAROUNDS )
# define BOOST_MP11_WORKAROUND( symbol, test ) 0
#else
# define BOOST_MP11_WORKAROUND( symbol, test ) ((symbol) != 0 && ((symbol) test))
#endif
//
#define BOOST_MP11_CUDA 0
#define BOOST_MP11_CLANG 0
#define BOOST_MP11_INTEL 0
#define BOOST_MP11_GCC 0
#define BOOST_MP11_MSVC 0
#define BOOST_MP11_CONSTEXPR constexpr
#if defined( __CUDACC__ )
// nvcc
# undef BOOST_MP11_CUDA
# define BOOST_MP11_CUDA (__CUDACC_VER_MAJOR__ * 1000000 + __CUDACC_VER_MINOR__ * 10000 + __CUDACC_VER_BUILD__)
// CUDA (8.0) has no constexpr support in msvc mode:
# if defined(_MSC_VER) && (BOOST_MP11_CUDA < 9000000)
# define BOOST_MP11_NO_CONSTEXPR
# undef BOOST_MP11_CONSTEXPR
# define BOOST_MP11_CONSTEXPR
# endif
#endif
#if defined(__clang__)
// Clang
# undef BOOST_MP11_CLANG
# define BOOST_MP11_CLANG (__clang_major__ * 100 + __clang_minor__)
# if defined(__has_cpp_attribute)
# if __has_cpp_attribute(fallthrough) && __cplusplus >= 201406L // Clang 3.9+ in c++1z mode
# define BOOST_MP11_HAS_FOLD_EXPRESSIONS
# endif
# endif
#if BOOST_MP11_CLANG < 400 && __cplusplus >= 201402L \
&& defined( __GLIBCXX__ ) && !__has_include(<shared_mutex>)
// Clang pre-4 in C++14 mode, libstdc++ pre-4.9, ::gets is not defined,
// but Clang tries to import it into std
extern "C" char *gets (char *__s);
#endif
#elif defined(__INTEL_COMPILER)
// Intel C++
# undef BOOST_MP11_INTEL
# define BOOST_MP11_INTEL __INTEL_COMPILER
#elif defined(__GNUC__)
// g++
# undef BOOST_MP11_GCC
# define BOOST_MP11_GCC (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#elif defined(_MSC_VER)
// MS Visual C++
# undef BOOST_MP11_MSVC
# define BOOST_MP11_MSVC _MSC_VER
# if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 )
# define BOOST_MP11_NO_CONSTEXPR
# endif
#if _MSC_FULL_VER < 190024210 // 2015u3
# undef BOOST_MP11_CONSTEXPR
# define BOOST_MP11_CONSTEXPR
#endif
#endif
// BOOST_MP11_HAS_CXX14_CONSTEXPR
#if !defined(BOOST_MP11_NO_CONSTEXPR) && defined(__cpp_constexpr) && __cpp_constexpr >= 201304
# define BOOST_MP11_HAS_CXX14_CONSTEXPR
#endif
// BOOST_MP11_HAS_FOLD_EXPRESSIONS
#if !defined(BOOST_MP11_HAS_FOLD_EXPRESSIONS) && defined(__cpp_fold_expressions) && __cpp_fold_expressions >= 201603
# define BOOST_MP11_HAS_FOLD_EXPRESSIONS
#endif
// BOOST_MP11_HAS_TYPE_PACK_ELEMENT
#if defined(__has_builtin)
# if __has_builtin(__type_pack_element)
# define BOOST_MP11_HAS_TYPE_PACK_ELEMENT
# endif
#endif
// BOOST_MP11_HAS_TEMPLATE_AUTO
#if defined(__cpp_nontype_template_parameter_auto) && __cpp_nontype_template_parameter_auto >= 201606L
# define BOOST_MP11_HAS_TEMPLATE_AUTO
#endif
#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 )
// mp_value<0> is bool, mp_value<-1L> is int, etc
# undef BOOST_MP11_HAS_TEMPLATE_AUTO
#endif
// BOOST_MP11_DEPRECATED(msg)
#if BOOST_MP11_WORKAROUND( BOOST_MP11_CLANG, < 304 )
# define BOOST_MP11_DEPRECATED(msg)
#elif defined(__GNUC__) || defined(__clang__)
# define BOOST_MP11_DEPRECATED(msg) __attribute__((deprecated(msg)))
#elif defined(_MSC_VER) && _MSC_VER >= 1900
# define BOOST_MP11_DEPRECATED(msg) [[deprecated(msg)]]
#else
# define BOOST_MP11_DEPRECATED(msg)
#endif
#endif // #ifndef BOOST_MP11_DETAIL_CONFIG_HPP_INCLUDED

View File

@@ -0,0 +1,321 @@
#ifndef BOOST_MP11_DETAIL_MP_APPEND_HPP_INCLUDED
#define BOOST_MP11_DETAIL_MP_APPEND_HPP_INCLUDED
// Copyright 2015-2017 Peter Dimov.
//
// 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/mp_count.hpp>
#include <boost/mp11/detail/mp_is_value_list.hpp>
#include <boost/mp11/detail/mp_list.hpp>
#include <boost/mp11/detail/mp_list_v.hpp>
#include <boost/mp11/utility.hpp>
#include <boost/mp11/detail/config.hpp>
namespace boost
{
namespace mp11
{
// mp_append<L...>
namespace detail
{
// append_type_lists
template<class... L> struct mp_append_impl;
#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 )
template<class... L> struct mp_append_impl
{
};
template<> struct mp_append_impl<>
{
using type = mp_list<>;
};
template<template<class...> class L, class... T> struct mp_append_impl<L<T...>>
{
using type = L<T...>;
};
template<template<class...> class L1, class... T1, template<class...> class L2, class... T2> struct mp_append_impl<L1<T1...>, L2<T2...>>
{
using type = L1<T1..., T2...>;
};
template<template<class...> class L1, class... T1, template<class...> class L2, class... T2, template<class...> class L3, class... T3> struct mp_append_impl<L1<T1...>, L2<T2...>, L3<T3...>>
{
using type = L1<T1..., T2..., T3...>;
};
template<template<class...> class L1, class... T1, template<class...> class L2, class... T2, template<class...> class L3, class... T3, template<class...> class L4, class... T4> struct mp_append_impl<L1<T1...>, L2<T2...>, L3<T3...>, L4<T4...>>
{
using type = L1<T1..., T2..., T3..., T4...>;
};
template<template<class...> class L1, class... T1, template<class...> class L2, class... T2, template<class...> class L3, class... T3, template<class...> class L4, class... T4, template<class...> class L5, class... T5, class... Lr> struct mp_append_impl<L1<T1...>, L2<T2...>, L3<T3...>, L4<T4...>, L5<T5...>, Lr...>
{
using type = typename mp_append_impl<L1<T1..., T2..., T3..., T4..., T5...>, Lr...>::type;
};
#else
template<class L1 = mp_list<>, class L2 = mp_list<>, class L3 = mp_list<>, class L4 = mp_list<>, class L5 = mp_list<>, class L6 = mp_list<>, class L7 = mp_list<>, class L8 = mp_list<>, class L9 = mp_list<>, class L10 = mp_list<>, class L11 = mp_list<>> struct append_11_impl
{
};
template<
template<class...> class L1, class... T1,
template<class...> class L2, class... T2,
template<class...> class L3, class... T3,
template<class...> class L4, class... T4,
template<class...> class L5, class... T5,
template<class...> class L6, class... T6,
template<class...> class L7, class... T7,
template<class...> class L8, class... T8,
template<class...> class L9, class... T9,
template<class...> class L10, class... T10,
template<class...> class L11, class... T11>
struct append_11_impl<L1<T1...>, L2<T2...>, L3<T3...>, L4<T4...>, L5<T5...>, L6<T6...>, L7<T7...>, L8<T8...>, L9<T9...>, L10<T10...>, L11<T11...>>
{
using type = L1<T1..., T2..., T3..., T4..., T5..., T6..., T7..., T8..., T9..., T10..., T11...>;
};
template<
class L00 = mp_list<>, class L01 = mp_list<>, class L02 = mp_list<>, class L03 = mp_list<>, class L04 = mp_list<>, class L05 = mp_list<>, class L06 = mp_list<>, class L07 = mp_list<>, class L08 = mp_list<>, class L09 = mp_list<>, class L0A = mp_list<>,
class L10 = mp_list<>, class L11 = mp_list<>, class L12 = mp_list<>, class L13 = mp_list<>, class L14 = mp_list<>, class L15 = mp_list<>, class L16 = mp_list<>, class L17 = mp_list<>, class L18 = mp_list<>, class L19 = mp_list<>,
class L20 = mp_list<>, class L21 = mp_list<>, class L22 = mp_list<>, class L23 = mp_list<>, class L24 = mp_list<>, class L25 = mp_list<>, class L26 = mp_list<>, class L27 = mp_list<>, class L28 = mp_list<>, class L29 = mp_list<>,
class L30 = mp_list<>, class L31 = mp_list<>, class L32 = mp_list<>, class L33 = mp_list<>, class L34 = mp_list<>, class L35 = mp_list<>, class L36 = mp_list<>, class L37 = mp_list<>, class L38 = mp_list<>, class L39 = mp_list<>,
class L40 = mp_list<>, class L41 = mp_list<>, class L42 = mp_list<>, class L43 = mp_list<>, class L44 = mp_list<>, class L45 = mp_list<>, class L46 = mp_list<>, class L47 = mp_list<>, class L48 = mp_list<>, class L49 = mp_list<>,
class L50 = mp_list<>, class L51 = mp_list<>, class L52 = mp_list<>, class L53 = mp_list<>, class L54 = mp_list<>, class L55 = mp_list<>, class L56 = mp_list<>, class L57 = mp_list<>, class L58 = mp_list<>, class L59 = mp_list<>,
class L60 = mp_list<>, class L61 = mp_list<>, class L62 = mp_list<>, class L63 = mp_list<>, class L64 = mp_list<>, class L65 = mp_list<>, class L66 = mp_list<>, class L67 = mp_list<>, class L68 = mp_list<>, class L69 = mp_list<>,
class L70 = mp_list<>, class L71 = mp_list<>, class L72 = mp_list<>, class L73 = mp_list<>, class L74 = mp_list<>, class L75 = mp_list<>, class L76 = mp_list<>, class L77 = mp_list<>, class L78 = mp_list<>, class L79 = mp_list<>,
class L80 = mp_list<>, class L81 = mp_list<>, class L82 = mp_list<>, class L83 = mp_list<>, class L84 = mp_list<>, class L85 = mp_list<>, class L86 = mp_list<>, class L87 = mp_list<>, class L88 = mp_list<>, class L89 = mp_list<>,
class L90 = mp_list<>, class L91 = mp_list<>, class L92 = mp_list<>, class L93 = mp_list<>, class L94 = mp_list<>, class L95 = mp_list<>, class L96 = mp_list<>, class L97 = mp_list<>, class L98 = mp_list<>, class L99 = mp_list<>,
class LA0 = mp_list<>, class LA1 = mp_list<>, class LA2 = mp_list<>, class LA3 = mp_list<>, class LA4 = mp_list<>, class LA5 = mp_list<>, class LA6 = mp_list<>, class LA7 = mp_list<>, class LA8 = mp_list<>, class LA9 = mp_list<>
> struct append_111_impl
{
using type = typename append_11_impl<
typename append_11_impl<L00, L01, L02, L03, L04, L05, L06, L07, L08, L09, L0A>::type,
typename append_11_impl<mp_list<>, L10, L11, L12, L13, L14, L15, L16, L17, L18, L19>::type,
typename append_11_impl<mp_list<>, L20, L21, L22, L23, L24, L25, L26, L27, L28, L29>::type,
typename append_11_impl<mp_list<>, L30, L31, L32, L33, L34, L35, L36, L37, L38, L39>::type,
typename append_11_impl<mp_list<>, L40, L41, L42, L43, L44, L45, L46, L47, L48, L49>::type,
typename append_11_impl<mp_list<>, L50, L51, L52, L53, L54, L55, L56, L57, L58, L59>::type,
typename append_11_impl<mp_list<>, L60, L61, L62, L63, L64, L65, L66, L67, L68, L69>::type,
typename append_11_impl<mp_list<>, L70, L71, L72, L73, L74, L75, L76, L77, L78, L79>::type,
typename append_11_impl<mp_list<>, L80, L81, L82, L83, L84, L85, L86, L87, L88, L89>::type,
typename append_11_impl<mp_list<>, L90, L91, L92, L93, L94, L95, L96, L97, L98, L99>::type,
typename append_11_impl<mp_list<>, LA0, LA1, LA2, LA3, LA4, LA5, LA6, LA7, LA8, LA9>::type
>::type;
};
template<
class L00, class L01, class L02, class L03, class L04, class L05, class L06, class L07, class L08, class L09, class L0A,
class L10, class L11, class L12, class L13, class L14, class L15, class L16, class L17, class L18, class L19,
class L20, class L21, class L22, class L23, class L24, class L25, class L26, class L27, class L28, class L29,
class L30, class L31, class L32, class L33, class L34, class L35, class L36, class L37, class L38, class L39,
class L40, class L41, class L42, class L43, class L44, class L45, class L46, class L47, class L48, class L49,
class L50, class L51, class L52, class L53, class L54, class L55, class L56, class L57, class L58, class L59,
class L60, class L61, class L62, class L63, class L64, class L65, class L66, class L67, class L68, class L69,
class L70, class L71, class L72, class L73, class L74, class L75, class L76, class L77, class L78, class L79,
class L80, class L81, class L82, class L83, class L84, class L85, class L86, class L87, class L88, class L89,
class L90, class L91, class L92, class L93, class L94, class L95, class L96, class L97, class L98, class L99,
class LA0, class LA1, class LA2, class LA3, class LA4, class LA5, class LA6, class LA7, class LA8, class LA9,
class... Lr
> struct append_inf_impl
{
using prefix = typename append_111_impl<
L00, L01, L02, L03, L04, L05, L06, L07, L08, L09, L0A,
L10, L11, L12, L13, L14, L15, L16, L17, L18, L19,
L20, L21, L22, L23, L24, L25, L26, L27, L28, L29,
L30, L31, L32, L33, L34, L35, L36, L37, L38, L39,
L40, L41, L42, L43, L44, L45, L46, L47, L48, L49,
L50, L51, L52, L53, L54, L55, L56, L57, L58, L59,
L60, L61, L62, L63, L64, L65, L66, L67, L68, L69,
L70, L71, L72, L73, L74, L75, L76, L77, L78, L79,
L80, L81, L82, L83, L84, L85, L86, L87, L88, L89,
L90, L91, L92, L93, L94, L95, L96, L97, L98, L99,
LA0, LA1, LA2, LA3, LA4, LA5, LA6, LA7, LA8, LA9
>::type;
using type = typename mp_append_impl<prefix, Lr...>::type;
};
#if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 )
template<class... L>
struct mp_append_impl_cuda_workaround
{
using type = mp_if_c<(sizeof...(L) > 111), mp_quote<append_inf_impl>, mp_if_c<(sizeof...(L) > 11), mp_quote<append_111_impl>, mp_quote<append_11_impl> > >;
};
template<class... L> struct mp_append_impl: mp_append_impl_cuda_workaround<L...>::type::template fn<L...>
{
};
#else
template<class... L> struct mp_append_impl:
mp_cond<
mp_bool<(sizeof...(L) > 111)>, mp_quote<append_inf_impl>,
mp_bool<(sizeof...(L) > 11)>, mp_quote<append_111_impl>,
mp_true, mp_quote<append_11_impl>
>::template fn<L...>
{
};
#endif // #if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 )
#endif // #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 )
struct append_type_lists
{
template<class... L> using fn = typename mp_append_impl<L...>::type;
};
// append_value_lists
#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO)
template<class... L> struct append_value_impl;
template<class L1 = mp_list_v<>, class L2 = mp_list_v<>, class L3 = mp_list_v<>, class L4 = mp_list_v<>, class L5 = mp_list_v<>, class L6 = mp_list_v<>, class L7 = mp_list_v<>, class L8 = mp_list_v<>, class L9 = mp_list_v<>, class L10 = mp_list_v<>, class L11 = mp_list_v<>> struct append_value_11_impl
{
};
template<
template<auto...> class L1, auto... T1,
template<auto...> class L2, auto... T2,
template<auto...> class L3, auto... T3,
template<auto...> class L4, auto... T4,
template<auto...> class L5, auto... T5,
template<auto...> class L6, auto... T6,
template<auto...> class L7, auto... T7,
template<auto...> class L8, auto... T8,
template<auto...> class L9, auto... T9,
template<auto...> class L10, auto... T10,
template<auto...> class L11, auto... T11>
struct append_value_11_impl<L1<T1...>, L2<T2...>, L3<T3...>, L4<T4...>, L5<T5...>, L6<T6...>, L7<T7...>, L8<T8...>, L9<T9...>, L10<T10...>, L11<T11...>>
{
using type = L1<T1..., T2..., T3..., T4..., T5..., T6..., T7..., T8..., T9..., T10..., T11...>;
};
template<
class L00 = mp_list_v<>, class L01 = mp_list_v<>, class L02 = mp_list_v<>, class L03 = mp_list_v<>, class L04 = mp_list_v<>, class L05 = mp_list_v<>, class L06 = mp_list_v<>, class L07 = mp_list_v<>, class L08 = mp_list_v<>, class L09 = mp_list_v<>, class L0A = mp_list_v<>,
class L10 = mp_list_v<>, class L11 = mp_list_v<>, class L12 = mp_list_v<>, class L13 = mp_list_v<>, class L14 = mp_list_v<>, class L15 = mp_list_v<>, class L16 = mp_list_v<>, class L17 = mp_list_v<>, class L18 = mp_list_v<>, class L19 = mp_list_v<>,
class L20 = mp_list_v<>, class L21 = mp_list_v<>, class L22 = mp_list_v<>, class L23 = mp_list_v<>, class L24 = mp_list_v<>, class L25 = mp_list_v<>, class L26 = mp_list_v<>, class L27 = mp_list_v<>, class L28 = mp_list_v<>, class L29 = mp_list_v<>,
class L30 = mp_list_v<>, class L31 = mp_list_v<>, class L32 = mp_list_v<>, class L33 = mp_list_v<>, class L34 = mp_list_v<>, class L35 = mp_list_v<>, class L36 = mp_list_v<>, class L37 = mp_list_v<>, class L38 = mp_list_v<>, class L39 = mp_list_v<>,
class L40 = mp_list_v<>, class L41 = mp_list_v<>, class L42 = mp_list_v<>, class L43 = mp_list_v<>, class L44 = mp_list_v<>, class L45 = mp_list_v<>, class L46 = mp_list_v<>, class L47 = mp_list_v<>, class L48 = mp_list_v<>, class L49 = mp_list_v<>,
class L50 = mp_list_v<>, class L51 = mp_list_v<>, class L52 = mp_list_v<>, class L53 = mp_list_v<>, class L54 = mp_list_v<>, class L55 = mp_list_v<>, class L56 = mp_list_v<>, class L57 = mp_list_v<>, class L58 = mp_list_v<>, class L59 = mp_list_v<>,
class L60 = mp_list_v<>, class L61 = mp_list_v<>, class L62 = mp_list_v<>, class L63 = mp_list_v<>, class L64 = mp_list_v<>, class L65 = mp_list_v<>, class L66 = mp_list_v<>, class L67 = mp_list_v<>, class L68 = mp_list_v<>, class L69 = mp_list_v<>,
class L70 = mp_list_v<>, class L71 = mp_list_v<>, class L72 = mp_list_v<>, class L73 = mp_list_v<>, class L74 = mp_list_v<>, class L75 = mp_list_v<>, class L76 = mp_list_v<>, class L77 = mp_list_v<>, class L78 = mp_list_v<>, class L79 = mp_list_v<>,
class L80 = mp_list_v<>, class L81 = mp_list_v<>, class L82 = mp_list_v<>, class L83 = mp_list_v<>, class L84 = mp_list_v<>, class L85 = mp_list_v<>, class L86 = mp_list_v<>, class L87 = mp_list_v<>, class L88 = mp_list_v<>, class L89 = mp_list_v<>,
class L90 = mp_list_v<>, class L91 = mp_list_v<>, class L92 = mp_list_v<>, class L93 = mp_list_v<>, class L94 = mp_list_v<>, class L95 = mp_list_v<>, class L96 = mp_list_v<>, class L97 = mp_list_v<>, class L98 = mp_list_v<>, class L99 = mp_list_v<>,
class LA0 = mp_list_v<>, class LA1 = mp_list_v<>, class LA2 = mp_list_v<>, class LA3 = mp_list_v<>, class LA4 = mp_list_v<>, class LA5 = mp_list_v<>, class LA6 = mp_list_v<>, class LA7 = mp_list_v<>, class LA8 = mp_list_v<>, class LA9 = mp_list_v<>
> struct append_value_111_impl
{
using type = typename append_value_11_impl<
typename append_value_11_impl<L00, L01, L02, L03, L04, L05, L06, L07, L08, L09, L0A>::type,
typename append_value_11_impl<mp_list_v<>, L10, L11, L12, L13, L14, L15, L16, L17, L18, L19>::type,
typename append_value_11_impl<mp_list_v<>, L20, L21, L22, L23, L24, L25, L26, L27, L28, L29>::type,
typename append_value_11_impl<mp_list_v<>, L30, L31, L32, L33, L34, L35, L36, L37, L38, L39>::type,
typename append_value_11_impl<mp_list_v<>, L40, L41, L42, L43, L44, L45, L46, L47, L48, L49>::type,
typename append_value_11_impl<mp_list_v<>, L50, L51, L52, L53, L54, L55, L56, L57, L58, L59>::type,
typename append_value_11_impl<mp_list_v<>, L60, L61, L62, L63, L64, L65, L66, L67, L68, L69>::type,
typename append_value_11_impl<mp_list_v<>, L70, L71, L72, L73, L74, L75, L76, L77, L78, L79>::type,
typename append_value_11_impl<mp_list_v<>, L80, L81, L82, L83, L84, L85, L86, L87, L88, L89>::type,
typename append_value_11_impl<mp_list_v<>, L90, L91, L92, L93, L94, L95, L96, L97, L98, L99>::type,
typename append_value_11_impl<mp_list_v<>, LA0, LA1, LA2, LA3, LA4, LA5, LA6, LA7, LA8, LA9>::type
>::type;
};
template<
class L00, class L01, class L02, class L03, class L04, class L05, class L06, class L07, class L08, class L09, class L0A,
class L10, class L11, class L12, class L13, class L14, class L15, class L16, class L17, class L18, class L19,
class L20, class L21, class L22, class L23, class L24, class L25, class L26, class L27, class L28, class L29,
class L30, class L31, class L32, class L33, class L34, class L35, class L36, class L37, class L38, class L39,
class L40, class L41, class L42, class L43, class L44, class L45, class L46, class L47, class L48, class L49,
class L50, class L51, class L52, class L53, class L54, class L55, class L56, class L57, class L58, class L59,
class L60, class L61, class L62, class L63, class L64, class L65, class L66, class L67, class L68, class L69,
class L70, class L71, class L72, class L73, class L74, class L75, class L76, class L77, class L78, class L79,
class L80, class L81, class L82, class L83, class L84, class L85, class L86, class L87, class L88, class L89,
class L90, class L91, class L92, class L93, class L94, class L95, class L96, class L97, class L98, class L99,
class LA0, class LA1, class LA2, class LA3, class LA4, class LA5, class LA6, class LA7, class LA8, class LA9,
class... Lr
> struct append_value_inf_impl
{
using prefix = typename append_value_111_impl<
L00, L01, L02, L03, L04, L05, L06, L07, L08, L09, L0A,
L10, L11, L12, L13, L14, L15, L16, L17, L18, L19,
L20, L21, L22, L23, L24, L25, L26, L27, L28, L29,
L30, L31, L32, L33, L34, L35, L36, L37, L38, L39,
L40, L41, L42, L43, L44, L45, L46, L47, L48, L49,
L50, L51, L52, L53, L54, L55, L56, L57, L58, L59,
L60, L61, L62, L63, L64, L65, L66, L67, L68, L69,
L70, L71, L72, L73, L74, L75, L76, L77, L78, L79,
L80, L81, L82, L83, L84, L85, L86, L87, L88, L89,
L90, L91, L92, L93, L94, L95, L96, L97, L98, L99,
LA0, LA1, LA2, LA3, LA4, LA5, LA6, LA7, LA8, LA9
>::type;
using type = typename append_value_impl<prefix, Lr...>::type;
};
template<class... L> struct append_value_impl:
mp_cond<
mp_bool<(sizeof...(L) > 111)>, mp_quote<append_value_inf_impl>,
mp_bool<(sizeof...(L) > 11)>, mp_quote<append_value_111_impl>,
mp_true, mp_quote<append_value_11_impl>
>::template fn<L...>
{
};
struct append_value_lists
{
template<class... L> using fn = typename append_value_impl<L...>::type;
};
#endif // #if defined(BOOST_MP11_HAS_TEMPLATE_AUTO)
} // namespace detail
#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO)
template<class... L> using mp_append = typename mp_if_c<(sizeof...(L) > 0 && sizeof...(L) == mp_count_if<mp_list<L...>, mp_is_value_list>::value), detail::append_value_lists, detail::append_type_lists>::template fn<L...>;
#else
template<class... L> using mp_append = detail::append_type_lists::fn<L...>;
#endif
} // namespace mp11
} // namespace boost
#endif // #ifndef BOOST_MP11_DETAIL_MP_APPEND_HPP_INCLUDED

View File

@@ -0,0 +1,48 @@
#ifndef BOOST_MP11_DETAIL_MP_COPY_IF_HPP_INCLUDED
#define BOOST_MP11_DETAIL_MP_COPY_IF_HPP_INCLUDED
// Copyright 2015-2019 Peter Dimov.
//
// 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/detail/mp_list.hpp>
#include <boost/mp11/detail/mp_append.hpp>
#include <boost/mp11/detail/config.hpp>
namespace boost
{
namespace mp11
{
// mp_copy_if<L, P>
namespace detail
{
template<class L, template<class...> class P> struct mp_copy_if_impl
{
};
template<template<class...> class L, class... T, template<class...> class P> struct mp_copy_if_impl<L<T...>, P>
{
#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 )
template<class U> struct _f { using type = mp_if<P<U>, mp_list<U>, mp_list<>>; };
using type = mp_append<L<>, typename _f<T>::type...>;
#else
template<class U> using _f = mp_if<P<U>, mp_list<U>, mp_list<>>;
using type = mp_append<L<>, _f<T>...>;
#endif
};
} // namespace detail
template<class L, template<class...> class P> using mp_copy_if = typename detail::mp_copy_if_impl<L, P>::type;
template<class L, class Q> using mp_copy_if_q = mp_copy_if<L, Q::template fn>;
} // namespace mp11
} // namespace boost
#endif // #ifndef BOOST_MP11_DETAIL_MP_COPY_IF_HPP_INCLUDED

View File

@@ -0,0 +1,147 @@
#ifndef BOOST_MP11_DETAIL_MP_COUNT_HPP_INCLUDED
#define BOOST_MP11_DETAIL_MP_COUNT_HPP_INCLUDED
// Copyright 2015, 2016 Peter Dimov.
//
// 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/integral.hpp>
#include <boost/mp11/detail/mp_plus.hpp>
#include <boost/mp11/detail/config.hpp>
namespace boost
{
namespace mp11
{
// mp_count<L, V>
namespace detail
{
#if !defined( BOOST_MP11_NO_CONSTEXPR )
constexpr std::size_t cx_plus()
{
return 0;
}
template<class T1, class... T> constexpr std::size_t cx_plus(T1 t1, T... t)
{
return static_cast<std::size_t>(t1) + cx_plus(t...);
}
template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class... T>
constexpr std::size_t cx_plus(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T... t)
{
return static_cast<std::size_t>(t1 + t2 + t3 + t4 + t5 + t6 + t7 + t8 + t9 + t10) + cx_plus(t...);
}
#endif
template<class L, class V> struct mp_count_impl;
#if defined( BOOST_MP11_HAS_CXX14_CONSTEXPR )
template<class V, class... T> constexpr std::size_t cx_count()
{
constexpr bool a[] = { false, std::is_same<T, V>::value... };
std::size_t r = 0;
for( std::size_t i = 1; i < sizeof...(T) + 1; ++i )
{
r += a[ i ];
}
return r;
}
template<template<class...> class L, class... T, class V> struct mp_count_impl<L<T...>, V>
{
using type = mp_size_t<cx_count<V, T...>()>;
};
#elif !defined( BOOST_MP11_NO_CONSTEXPR )
template<template<class...> class L, class... T, class V> struct mp_count_impl<L<T...>, V>
{
using type = mp_size_t<cx_plus(std::is_same<T, V>::value...)>;
};
#else
template<template<class...> class L, class... T, class V> struct mp_count_impl<L<T...>, V>
{
using type = mp_size_t<mp_plus<std::is_same<T, V>...>::value>;
};
#endif
} // namespace detail
template<class L, class V> using mp_count = typename detail::mp_count_impl<L, V>::type;
// mp_count_if<L, P>
namespace detail
{
template<class L, template<class...> class P> struct mp_count_if_impl;
#if defined( BOOST_MP11_HAS_CXX14_CONSTEXPR ) && !BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1930 )
template<template<class...> class P, class... T> constexpr std::size_t cx_count_if()
{
constexpr bool a[] = { false, static_cast<bool>( P<T>::value )... };
std::size_t r = 0;
for( std::size_t i = 1; i < sizeof...(T) + 1; ++i )
{
r += a[ i ];
}
return r;
}
template<template<class...> class L, class... T, template<class...> class P> struct mp_count_if_impl<L<T...>, P>
{
using type = mp_size_t<cx_count_if<P, T...>()>;
};
#elif !defined( BOOST_MP11_NO_CONSTEXPR )
template<template<class...> class L, class... T, template<class...> class P> struct mp_count_if_impl<L<T...>, P>
{
using type = mp_size_t<cx_plus(mp_to_bool<P<T>>::value...)>;
};
#else
template<template<class...> class L, class... T, template<class...> class P> struct mp_count_if_impl<L<T...>, P>
{
#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 )
template<class T> struct _f { using type = mp_to_bool<P<T>>; };
using type = mp_size_t<mp_plus<typename _f<T>::type...>::value>;
#else
using type = mp_size_t<mp_plus<mp_to_bool<P<T>>...>::value>;
#endif
};
#endif
} // namespace detail
template<class L, template<class...> class P> using mp_count_if = typename detail::mp_count_if_impl<L, P>::type;
template<class L, class Q> using mp_count_if_q = mp_count_if<L, Q::template fn>;
} // namespace mp11
} // namespace boost
#endif // #ifndef BOOST_MP11_DETAIL_MP_COUNT_HPP_INCLUDED

View File

@@ -0,0 +1,119 @@
#ifndef BOOST_MP11_DETAIL_MP_DEFER_HPP_INCLUDED
#define BOOST_MP11_DETAIL_MP_DEFER_HPP_INCLUDED
// Copyright 2015-2020, 2023 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/mp11/integral.hpp>
#include <boost/mp11/detail/config.hpp>
namespace boost
{
namespace mp11
{
// mp_if, mp_if_c
namespace detail
{
template<bool C, class T, class... E> struct mp_if_c_impl
{
};
template<class T, class... E> struct mp_if_c_impl<true, T, E...>
{
using type = T;
};
template<class T, class E> struct mp_if_c_impl<false, T, E>
{
using type = E;
};
} // namespace detail
template<bool C, class T, class... E> using mp_if_c = typename detail::mp_if_c_impl<C, T, E...>::type;
template<class C, class T, class... E> using mp_if = typename detail::mp_if_c_impl<static_cast<bool>(C::value), T, E...>::type;
// mp_valid
#if BOOST_MP11_WORKAROUND( BOOST_MP11_INTEL, != 0 ) // tested at 1800
// contributed by Roland Schulz in https://github.com/boostorg/mp11/issues/17
namespace detail
{
template<class...> using void_t = void;
template<class, template<class...> class F, class... T>
struct mp_valid_impl: mp_false {};
template<template<class...> class F, class... T>
struct mp_valid_impl<void_t<F<T...>>, F, T...>: mp_true {};
} // namespace detail
template<template<class...> class F, class... T> using mp_valid = typename detail::mp_valid_impl<void, F, T...>;
#else
// implementation by Bruno Dutra (by the name is_evaluable)
namespace detail
{
template<template<class...> class F, class... T> struct mp_valid_impl
{
template<template<class...> class G, class = G<T...>> static mp_true check(int);
template<template<class...> class> static mp_false check(...);
using type = decltype(check<F>(0));
};
} // namespace detail
template<template<class...> class F, class... T> using mp_valid = typename detail::mp_valid_impl<F, T...>::type;
#endif
template<class Q, class... T> using mp_valid_q = mp_valid<Q::template fn, T...>;
// mp_defer
namespace detail
{
template<template<class...> class F, class... T> struct mp_defer_impl
{
using type = F<T...>;
};
struct mp_no_type
{
};
#if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 )
template<template<class...> class F, class... T> struct mp_defer_cuda_workaround
{
using type = mp_if<mp_valid<F, T...>, detail::mp_defer_impl<F, T...>, detail::mp_no_type>;
};
#endif
} // namespace detail
#if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 )
template<template<class...> class F, class... T> using mp_defer = typename detail::mp_defer_cuda_workaround< F, T...>::type;
#else
template<template<class...> class F, class... T> using mp_defer = mp_if<mp_valid<F, T...>, detail::mp_defer_impl<F, T...>, detail::mp_no_type>;
#endif
} // namespace mp11
} // namespace boost
#endif // #ifndef BOOST_MP11_DETAIL_MP_DEFER_HPP_INCLUDED

View File

@@ -0,0 +1,164 @@
#ifndef BOOST_MP11_DETAIL_MP_FOLD_HPP_INCLUDED
#define BOOST_MP11_DETAIL_MP_FOLD_HPP_INCLUDED
// Copyright 2015-2017 Peter Dimov.
//
// 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>
#include <boost/mp11/detail/mp_defer.hpp>
namespace boost
{
namespace mp11
{
// mp_fold<L, V, F>
namespace detail
{
template<class L, class V, template<class...> class F> struct mp_fold_impl
{
// An error "no type named 'type'" here means that the first argument to mp_fold is not a list
};
#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 )
template<template<class...> class L, class... T, class V, template<class...> class F> struct mp_fold_impl<L<T...>, V, F>
{
static_assert( sizeof...(T) == 0, "T... must be empty" );
using type = V;
};
#else
template<template<class...> class L, class V, template<class...> class F> struct mp_fold_impl<L<>, V, F>
{
using type = V;
};
#endif
//
template<class V, template<class...> class F> struct mp_fold_Q1
{
template<class T1>
using fn = F<V, T1>;
};
template<class V, template<class...> class F> struct mp_fold_Q2
{
template<class T1, class T2>
using fn = F<F<V, T1>, T2>;
};
template<class V, template<class...> class F> struct mp_fold_Q3
{
template<class T1, class T2, class T3>
using fn = F<F<F<V, T1>, T2>, T3>;
};
template<class V, template<class...> class F> struct mp_fold_Q4
{
template<class T1, class T2, class T3, class T4>
using fn = F<F<F<F<V, T1>, T2>, T3>, T4>;
};
template<class V, template<class...> class F> struct mp_fold_Q5
{
template<class T1, class T2, class T3, class T4, class T5>
using fn = F<F<F<F<F<V, T1>, T2>, T3>, T4>, T5>;
};
template<class V, template<class...> class F> struct mp_fold_Q6
{
template<class T1, class T2, class T3, class T4, class T5, class T6>
using fn = F<F<F<F<F<F<V, T1>, T2>, T3>, T4>, T5>, T6>;
};
template<class V, template<class...> class F> struct mp_fold_Q7
{
template<class T1, class T2, class T3, class T4, class T5, class T6, class T7>
using fn = F<F<F<F<F<F<F<V, T1>, T2>, T3>, T4>, T5>, T6>, T7>;
};
template<class V, template<class...> class F> struct mp_fold_Q8
{
template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
using fn = F<F<F<F<F<F<F<F<V, T1>, T2>, T3>, T4>, T5>, T6>, T7>, T8>;
};
template<class V, template<class...> class F> struct mp_fold_Q9
{
template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9>
using fn = F<F<F<F<F<F<F<F<F<V, T1>, T2>, T3>, T4>, T5>, T6>, T7>, T8>, T9>;
};
//
template<template<class...> class L, class T1, class V, template<class...> class F>
struct mp_fold_impl<L<T1>, V, F>: mp_defer<mp_fold_Q1<V, F>::template fn, T1>
{
};
template<template<class...> class L, class T1, class T2, class V, template<class...> class F>
struct mp_fold_impl<L<T1, T2>, V, F>: mp_defer<mp_fold_Q2<V, F>::template fn, T1, T2>
{
};
template<template<class...> class L, class T1, class T2, class T3, class V, template<class...> class F>
struct mp_fold_impl<L<T1, T2, T3>, V, F>: mp_defer<mp_fold_Q3<V, F>::template fn, T1, T2, T3>
{
};
template<template<class...> class L, class T1, class T2, class T3, class T4, class V, template<class...> class F>
struct mp_fold_impl<L<T1, T2, T3, T4>, V, F>: mp_defer<mp_fold_Q4<V, F>::template fn, T1, T2, T3, T4>
{
};
template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class V, template<class...> class F>
struct mp_fold_impl<L<T1, T2, T3, T4, T5>, V, F>: mp_defer<mp_fold_Q5<V, F>::template fn, T1, T2, T3, T4, T5>
{
};
template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class T6, class V, template<class...> class F>
struct mp_fold_impl<L<T1, T2, T3, T4, T5, T6>, V, F>: mp_defer<mp_fold_Q6<V, F>::template fn, T1, T2, T3, T4, T5, T6>
{
};
template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class V, template<class...> class F>
struct mp_fold_impl<L<T1, T2, T3, T4, T5, T6, T7>, V, F>: mp_defer<mp_fold_Q7<V, F>::template fn, T1, T2, T3, T4, T5, T6, T7>
{
};
template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class V, template<class...> class F>
struct mp_fold_impl<L<T1, T2, T3, T4, T5, T6, T7, T8>, V, F>: mp_defer<mp_fold_Q8<V, F>::template fn, T1, T2, T3, T4, T5, T6, T7, T8>
{
};
template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class V, template<class...> class F>
struct mp_fold_impl<L<T1, T2, T3, T4, T5, T6, T7, T8, T9>, V, F>: mp_defer<mp_fold_Q9<V, F>::template fn, T1, T2, T3, T4, T5, T6, T7, T8, T9>
{
};
//
template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class... T, class V, template<class...> class F>
struct mp_fold_impl<L<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T...>, V, F>
{
using type = typename mp_fold_impl<L<T...>, F<F<F<F<F<F<F<F<F<F<V, T1>, T2>, T3>, T4>, T5>, T6>, T7>, T8>, T9>, T10>, F>::type;
};
} // namespace detail
template<class L, class V, template<class...> class F> using mp_fold = typename detail::mp_fold_impl<L, V, F>::type;
template<class L, class V, class Q> using mp_fold_q = mp_fold<L, V, Q::template fn>;
} // namespace mp11
} // namespace boost
#endif // #ifndef BOOST_MP11_DETAIL_MP_FOLD_HPP_INCLUDED

View File

@@ -0,0 +1,50 @@
#ifndef BOOST_MP11_DETAIL_MP_FRONT_HPP_INCLUDED
#define BOOST_MP11_DETAIL_MP_FRONT_HPP_INCLUDED
// Copyright 2015-2023 Peter Dimov.
//
// 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/mp_value.hpp>
#include <boost/mp11/detail/config.hpp>
namespace boost
{
namespace mp11
{
// mp_front<L>
namespace detail
{
template<class L> struct mp_front_impl
{
// An error "no type named 'type'" here means that the argument to mp_front
// is either not a list, or is an empty list
};
template<template<class...> class L, class T1, class... T> struct mp_front_impl<L<T1, T...>>
{
using type = T1;
};
#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO)
template<template<auto...> class L, auto A1, auto... A> struct mp_front_impl<L<A1, A...>>
{
using type = mp_value<A1>;
};
#endif
} // namespace detail
template<class L> using mp_front = typename detail::mp_front_impl<L>::type;
} // namespace mp11
} // namespace boost
#endif // #ifndef BOOST_MP11_DETAIL_MP_FRONT_HPP_INCLUDED

View File

@@ -0,0 +1,39 @@
#ifndef BOOST_MP11_DETAIL_MP_IS_LIST_HPP_INCLUDED
#define BOOST_MP11_DETAIL_MP_IS_LIST_HPP_INCLUDED
// Copyright 2015-2019 Peter Dimov.
//
// 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/integral.hpp>
namespace boost
{
namespace mp11
{
// mp_is_list<L>
namespace detail
{
template<class L> struct mp_is_list_impl
{
using type = mp_false;
};
template<template<class...> class L, class... T> struct mp_is_list_impl<L<T...>>
{
using type = mp_true;
};
} // namespace detail
template<class L> using mp_is_list = typename detail::mp_is_list_impl<L>::type;
} // namespace mp11
} // namespace boost
#endif // #ifndef BOOST_MP11_DETAIL_MP_IS_LIST_HPP_INCLUDED

View File

@@ -0,0 +1,41 @@
#ifndef BOOST_MP11_DETAIL_MP_IS_VALUE_LIST_HPP_INCLUDED
#define BOOST_MP11_DETAIL_MP_IS_VALUE_LIST_HPP_INCLUDED
// Copyright 2023 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/mp11/integral.hpp>
#include <boost/mp11/detail/config.hpp>
namespace boost
{
namespace mp11
{
// mp_is_value_list<L>
namespace detail
{
template<class L> struct mp_is_value_list_impl
{
using type = mp_false;
};
#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO)
template<template<auto...> class L, auto... A> struct mp_is_value_list_impl<L<A...>>
{
using type = mp_true;
};
#endif
} // namespace detail
template<class L> using mp_is_value_list = typename detail::mp_is_value_list_impl<L>::type;
} // namespace mp11
} // namespace boost
#endif // #ifndef BOOST_MP11_DETAIL_MP_IS_VALUE_LIST_HPP_INCLUDED

View File

@@ -0,0 +1,24 @@
#ifndef BOOST_MP11_DETAIL_MP_LIST_HPP_INCLUDED
#define BOOST_MP11_DETAIL_MP_LIST_HPP_INCLUDED
// Copyright 2015, 2016 Peter Dimov.
//
// 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
namespace boost
{
namespace mp11
{
// mp_list<T...>
template<class... T> struct mp_list
{
};
} // namespace mp11
} // namespace boost
#endif // #ifndef BOOST_MP11_DETAIL_MP_LIST_HPP_INCLUDED

View File

@@ -0,0 +1,27 @@
#ifndef BOOST_MP11_DETAIL_MP_LIST_V_HPP_INCLUDED
#define BOOST_MP11_DETAIL_MP_LIST_V_HPP_INCLUDED
// Copyright 2023 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/mp11/detail/config.hpp>
namespace boost
{
namespace mp11
{
#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO)
// mp_list_v<A...>
template<auto... A> struct mp_list_v
{
};
#endif
} // namespace mp11
} // namespace boost
#endif // #ifndef BOOST_MP11_DETAIL_MP_LIST_V_HPP_INCLUDED

View File

@@ -0,0 +1,87 @@
#ifndef BOOST_MP11_DETAIL_MP_MAP_FIND_HPP_INCLUDED
#define BOOST_MP11_DETAIL_MP_MAP_FIND_HPP_INCLUDED
// Copyright 2015 Peter Dimov.
//
// 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/detail/config.hpp>
#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1930 )
// not exactly good practice, but...
namespace std
{
template<class... _Types> class tuple;
}
#endif
namespace boost
{
namespace mp11
{
// mp_map_find
namespace detail
{
#if !BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1930 )
template<class T> using mpmf_wrap = mp_identity<T>;
template<class T> using mpmf_unwrap = typename T::type;
#else
template<class... T> struct mpmf_tuple {};
template<class T> struct mpmf_wrap_impl
{
using type = mp_identity<T>;
};
template<class... T> struct mpmf_wrap_impl< std::tuple<T...> >
{
using type = mp_identity< mpmf_tuple<T...> >;
};
template<class T> using mpmf_wrap = typename mpmf_wrap_impl<T>::type;
template<class T> struct mpmf_unwrap_impl
{
using type = typename T::type;
};
template<class... T> struct mpmf_unwrap_impl< mp_identity< mpmf_tuple<T...> > >
{
using type = std::tuple<T...>;
};
template<class T> using mpmf_unwrap = typename mpmf_unwrap_impl<T>::type;
#endif // #if !BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1930 )
template<class M, class K> struct mp_map_find_impl;
template<template<class...> class M, class... T, class K> struct mp_map_find_impl<M<T...>, K>
{
using U = mp_inherit<mpmf_wrap<T>...>;
template<template<class...> class L, class... U> static mp_identity<L<K, U...>> f( mp_identity<L<K, U...>>* );
static mp_identity<void> f( ... );
using type = mpmf_unwrap< decltype( f( static_cast<U*>(0) ) ) >;
};
} // namespace detail
template<class M, class K> using mp_map_find = typename detail::mp_map_find_impl<M, K>::type;
} // namespace mp11
} // namespace boost
#endif // #ifndef BOOST_MP11_DETAIL_MP_MAP_FIND_HPP_INCLUDED

View File

@@ -0,0 +1,51 @@
#ifndef BOOST_MP11_DETAIL_MP_MIN_ELEMENT_HPP_INCLUDED
#define BOOST_MP11_DETAIL_MP_MIN_ELEMENT_HPP_INCLUDED
// Copyright 2015-2017 Peter Dimov.
//
// 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/mp_fold.hpp>
#include <boost/mp11/list.hpp>
#include <boost/mp11/utility.hpp>
namespace boost
{
namespace mp11
{
// mp_min_element<L, P>
namespace detail
{
template<template<class...> class P> struct select_min
{
template<class T1, class T2> using fn = mp_if<P<T1, T2>, T1, T2>;
};
} // namespace detail
template<class L, template<class...> class P> using mp_min_element = mp_fold_q<mp_rest<L>, mp_first<L>, detail::select_min<P>>;
template<class L, class Q> using mp_min_element_q = mp_min_element<L, Q::template fn>;
// mp_max_element<L, P>
namespace detail
{
template<template<class...> class P> struct select_max
{
template<class T1, class T2> using fn = mp_if<P<T2, T1>, T1, T2>;
};
} // namespace detail
template<class L, template<class...> class P> using mp_max_element = mp_fold_q<mp_rest<L>, mp_first<L>, detail::select_max<P>>;
template<class L, class Q> using mp_max_element_q = mp_max_element<L, Q::template fn>;
} // namespace mp11
} // namespace boost
#endif // #ifndef BOOST_MP11_DETAIL_MP_MIN_ELEMENT_HPP_INCLUDED

View File

@@ -0,0 +1,84 @@
#ifndef BOOST_MP11_DETAIL_MP_PLUS_HPP_INCLUDED
#define BOOST_MP11_DETAIL_MP_PLUS_HPP_INCLUDED
// Copyright 2015 Peter Dimov.
//
// 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>
#include <type_traits>
namespace boost
{
namespace mp11
{
// mp_plus
namespace detail
{
#if defined( BOOST_MP11_HAS_FOLD_EXPRESSIONS ) && !BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, != 0 ) && !BOOST_MP11_WORKAROUND( BOOST_MP11_CLANG, != 0 )
// msvc fails with parser stack overflow for large sizeof...(T)
// clang exceeds -fbracket-depth, which defaults to 256
template<class... T> struct mp_plus_impl
{
static const auto _v = (T::value + ... + 0);
using type = std::integral_constant<typename std::remove_const<decltype(_v)>::type, _v>;
};
#else
template<class... T> struct mp_plus_impl;
template<> struct mp_plus_impl<>
{
using type = std::integral_constant<int, 0>;
};
#if BOOST_MP11_WORKAROUND( BOOST_MP11_GCC, < 40800 )
template<class T1, class... T> struct mp_plus_impl<T1, T...>
{
static const decltype(T1::value + mp_plus_impl<T...>::type::value) _v = T1::value + mp_plus_impl<T...>::type::value;
using type = std::integral_constant<typename std::remove_const<decltype(_v)>::type, _v>;
};
template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class... T> struct mp_plus_impl<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T...>
{
static const
decltype(T1::value + T2::value + T3::value + T4::value + T5::value + T6::value + T7::value + T8::value + T9::value + T10::value + mp_plus_impl<T...>::type::value)
_v = T1::value + T2::value + T3::value + T4::value + T5::value + T6::value + T7::value + T8::value + T9::value + T10::value + mp_plus_impl<T...>::type::value;
using type = std::integral_constant<typename std::remove_const<decltype(_v)>::type, _v>;
};
#else
template<class T1, class... T> struct mp_plus_impl<T1, T...>
{
static const auto _v = T1::value + mp_plus_impl<T...>::type::value;
using type = std::integral_constant<typename std::remove_const<decltype(_v)>::type, _v>;
};
template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class... T> struct mp_plus_impl<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T...>
{
static const auto _v = T1::value + T2::value + T3::value + T4::value + T5::value + T6::value + T7::value + T8::value + T9::value + T10::value + mp_plus_impl<T...>::type::value;
using type = std::integral_constant<typename std::remove_const<decltype(_v)>::type, _v>;
};
#endif
#endif
} // namespace detail
template<class... T> using mp_plus = typename detail::mp_plus_impl<T...>::type;
} // namespace mp11
} // namespace boost
#endif // #ifndef BOOST_MP11_DETAIL_MP_PLUS_HPP_INCLUDED

View File

@@ -0,0 +1,48 @@
#ifndef BOOST_MP11_DETAIL_MP_REMOVE_IF_HPP_INCLUDED
#define BOOST_MP11_DETAIL_MP_REMOVE_IF_HPP_INCLUDED
// Copyright 2015-2019 Peter Dimov.
//
// 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/detail/mp_list.hpp>
#include <boost/mp11/detail/mp_append.hpp>
#include <boost/mp11/detail/config.hpp>
namespace boost
{
namespace mp11
{
// mp_remove_if<L, P>
namespace detail
{
template<class L, template<class...> class P> struct mp_remove_if_impl
{
};
template<template<class...> class L, class... T, template<class...> class P> struct mp_remove_if_impl<L<T...>, P>
{
#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 )
template<class U> struct _f { using type = mp_if<P<U>, mp_list<>, mp_list<U>>; };
using type = mp_append<L<>, typename _f<T>::type...>;
#else
template<class U> using _f = mp_if<P<U>, mp_list<>, mp_list<U>>;
using type = mp_append<L<>, _f<T>...>;
#endif
};
} // namespace detail
template<class L, template<class...> class P> using mp_remove_if = typename detail::mp_remove_if_impl<L, P>::type;
template<class L, class Q> using mp_remove_if_q = mp_remove_if<L, Q::template fn>;
} // namespace mp11
} // namespace boost
#endif // #ifndef BOOST_MP11_DETAIL_MP_REMOVE_IF_HPP_INCLUDED

View File

@@ -0,0 +1,54 @@
#ifndef BOOST_MP11_DETAIL_MP_RENAME_HPP_INCLUDED
#define BOOST_MP11_DETAIL_MP_RENAME_HPP_INCLUDED
// Copyright 2015-2023 Peter Dimov.
//
// 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/mp_defer.hpp>
#include <boost/mp11/detail/mp_value.hpp>
#include <boost/mp11/detail/config.hpp>
namespace boost
{
namespace mp11
{
// mp_rename<L, B>
namespace detail
{
template<class L, template<class...> class B> struct mp_rename_impl
{
// An error "no type named 'type'" here means that the first argument to mp_rename is not a list
};
template<template<class...> class L, class... T, template<class...> class B> struct mp_rename_impl<L<T...>, B>: mp_defer<B, T...>
{
};
#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO)
template<template<auto...> class L, auto... A, template<class...> class B> struct mp_rename_impl<L<A...>, B>: mp_defer<B, mp_value<A>...>
{
};
#endif
} // namespace detail
template<class L, template<class...> class B> using mp_rename = typename detail::mp_rename_impl<L, B>::type;
// mp_apply<F, L>
template<template<class...> class F, class L> using mp_apply = typename detail::mp_rename_impl<L, F>::type;
// mp_apply_q<Q, L>
template<class Q, class L> using mp_apply_q = typename detail::mp_rename_impl<L, Q::template fn>::type;
} // namespace mp11
} // namespace boost
#endif // #ifndef BOOST_MP11_DETAIL_MP_RENAME_HPP_INCLUDED

View File

@@ -0,0 +1,25 @@
#ifndef BOOST_MP11_DETAIL_MP_VALUE_HPP_INCLUDED
#define BOOST_MP11_DETAIL_MP_VALUE_HPP_INCLUDED
// Copyright 2023 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/mp11/detail/config.hpp>
#include <type_traits>
#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO)
namespace boost
{
namespace mp11
{
template<auto A> using mp_value = std::integral_constant<decltype(A), A>;
} // namespace mp11
} // namespace boost
#endif // #if defined(BOOST_MP11_HAS_TEMPLATE_AUTO)
#endif // #ifndef BOOST_MP11_DETAIL_MP_VALUE_HPP_INCLUDED

View File

@@ -0,0 +1,32 @@
#ifndef BOOST_MP11_DETAIL_MP_VOID_HPP_INCLUDED
#define BOOST_MP11_DETAIL_MP_VOID_HPP_INCLUDED
// Copyright 2015-2017 Peter Dimov.
//
// 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
namespace boost
{
namespace mp11
{
// mp_void<T...>
namespace detail
{
template<class... T> struct mp_void_impl
{
using type = void;
};
} // namespace detail
template<class... T> using mp_void = typename detail::mp_void_impl<T...>::type;
} // namespace mp11
} // namespace boost
#endif // #ifndef BOOST_MP11_DETAIL_MP_VOID_HPP_INCLUDED

View File

@@ -0,0 +1,385 @@
#ifndef BOOST_MP11_DETAIL_MP_WITH_INDEX_HPP_INCLUDED
#define BOOST_MP11_DETAIL_MP_WITH_INDEX_HPP_INCLUDED
// Copyright 2017 Peter Dimov.
//
// 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/integral.hpp>
#include <boost/mp11/detail/config.hpp>
#include <type_traits>
#include <utility>
#include <cassert>
#if defined( BOOST_MP11_HAS_CXX14_CONSTEXPR )
# define BOOST_MP11_CONSTEXPR14 constexpr
#else
# define BOOST_MP11_CONSTEXPR14
#endif
#if defined( __GNUC__ ) || defined( __clang__ )
# define BOOST_MP11_UNREACHABLE_DEFAULT default: __builtin_unreachable();
#elif defined( _MSC_VER )
# define BOOST_MP11_UNREACHABLE_DEFAULT default: __assume(false);
#else
# define BOOST_MP11_UNREACHABLE_DEFAULT
#endif
namespace boost
{
namespace mp11
{
namespace detail
{
template<std::size_t N> struct mp_with_index_impl_
{
template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
{
if( i < N / 2 )
{
return mp_with_index_impl_<N/2>::template call<K>( i, std::forward<F>(f) );
}
else
{
return mp_with_index_impl_<N-N/2>::template call<K+N/2>( i - N/2, std::forward<F>(f) );
}
}
};
template<> struct mp_with_index_impl_<0>
{
};
template<> struct mp_with_index_impl_<1>
{
template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t /*i*/, F && f )
{
return std::forward<F>(f)( mp_size_t<K+0>() );
}
};
template<> struct mp_with_index_impl_<2>
{
template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
{
switch( i )
{
BOOST_MP11_UNREACHABLE_DEFAULT
case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
}
}
};
template<> struct mp_with_index_impl_<3>
{
template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
{
switch( i )
{
BOOST_MP11_UNREACHABLE_DEFAULT
case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
}
}
};
template<> struct mp_with_index_impl_<4>
{
template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
{
switch( i )
{
BOOST_MP11_UNREACHABLE_DEFAULT
case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
}
}
};
template<> struct mp_with_index_impl_<5>
{
template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
{
switch( i )
{
BOOST_MP11_UNREACHABLE_DEFAULT
case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
}
}
};
template<> struct mp_with_index_impl_<6>
{
template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
{
switch( i )
{
BOOST_MP11_UNREACHABLE_DEFAULT
case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
}
}
};
template<> struct mp_with_index_impl_<7>
{
template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
{
switch( i )
{
BOOST_MP11_UNREACHABLE_DEFAULT
case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
}
}
};
template<> struct mp_with_index_impl_<8>
{
template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
{
switch( i )
{
BOOST_MP11_UNREACHABLE_DEFAULT
case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
}
}
};
template<> struct mp_with_index_impl_<9>
{
template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
{
switch( i )
{
BOOST_MP11_UNREACHABLE_DEFAULT
case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
case 8: return std::forward<F>(f)( mp_size_t<K+8>() );
}
}
};
template<> struct mp_with_index_impl_<10>
{
template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
{
switch( i )
{
BOOST_MP11_UNREACHABLE_DEFAULT
case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
case 8: return std::forward<F>(f)( mp_size_t<K+8>() );
case 9: return std::forward<F>(f)( mp_size_t<K+9>() );
}
}
};
template<> struct mp_with_index_impl_<11>
{
template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
{
switch( i )
{
BOOST_MP11_UNREACHABLE_DEFAULT
case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
case 8: return std::forward<F>(f)( mp_size_t<K+8>() );
case 9: return std::forward<F>(f)( mp_size_t<K+9>() );
case 10: return std::forward<F>(f)( mp_size_t<K+10>() );
}
}
};
template<> struct mp_with_index_impl_<12>
{
template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
{
switch( i )
{
BOOST_MP11_UNREACHABLE_DEFAULT
case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
case 8: return std::forward<F>(f)( mp_size_t<K+8>() );
case 9: return std::forward<F>(f)( mp_size_t<K+9>() );
case 10: return std::forward<F>(f)( mp_size_t<K+10>() );
case 11: return std::forward<F>(f)( mp_size_t<K+11>() );
}
}
};
template<> struct mp_with_index_impl_<13>
{
template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
{
switch( i )
{
BOOST_MP11_UNREACHABLE_DEFAULT
case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
case 8: return std::forward<F>(f)( mp_size_t<K+8>() );
case 9: return std::forward<F>(f)( mp_size_t<K+9>() );
case 10: return std::forward<F>(f)( mp_size_t<K+10>() );
case 11: return std::forward<F>(f)( mp_size_t<K+11>() );
case 12: return std::forward<F>(f)( mp_size_t<K+12>() );
}
}
};
template<> struct mp_with_index_impl_<14>
{
template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
{
switch( i )
{
BOOST_MP11_UNREACHABLE_DEFAULT
case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
case 8: return std::forward<F>(f)( mp_size_t<K+8>() );
case 9: return std::forward<F>(f)( mp_size_t<K+9>() );
case 10: return std::forward<F>(f)( mp_size_t<K+10>() );
case 11: return std::forward<F>(f)( mp_size_t<K+11>() );
case 12: return std::forward<F>(f)( mp_size_t<K+12>() );
case 13: return std::forward<F>(f)( mp_size_t<K+13>() );
}
}
};
template<> struct mp_with_index_impl_<15>
{
template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
{
switch( i )
{
BOOST_MP11_UNREACHABLE_DEFAULT
case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
case 8: return std::forward<F>(f)( mp_size_t<K+8>() );
case 9: return std::forward<F>(f)( mp_size_t<K+9>() );
case 10: return std::forward<F>(f)( mp_size_t<K+10>() );
case 11: return std::forward<F>(f)( mp_size_t<K+11>() );
case 12: return std::forward<F>(f)( mp_size_t<K+12>() );
case 13: return std::forward<F>(f)( mp_size_t<K+13>() );
case 14: return std::forward<F>(f)( mp_size_t<K+14>() );
}
}
};
template<> struct mp_with_index_impl_<16>
{
template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
{
switch( i )
{
BOOST_MP11_UNREACHABLE_DEFAULT
case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
case 8: return std::forward<F>(f)( mp_size_t<K+8>() );
case 9: return std::forward<F>(f)( mp_size_t<K+9>() );
case 10: return std::forward<F>(f)( mp_size_t<K+10>() );
case 11: return std::forward<F>(f)( mp_size_t<K+11>() );
case 12: return std::forward<F>(f)( mp_size_t<K+12>() );
case 13: return std::forward<F>(f)( mp_size_t<K+13>() );
case 14: return std::forward<F>(f)( mp_size_t<K+14>() );
case 15: return std::forward<F>(f)( mp_size_t<K+15>() );
}
}
};
} // namespace detail
template<std::size_t N, class F> inline BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) mp_with_index( std::size_t i, F && f )
{
assert( i < N );
return detail::mp_with_index_impl_<N>::template call<0>( i, std::forward<F>(f) );
}
template<class N, class F> inline BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) mp_with_index( std::size_t i, F && f )
{
return mp_with_index<std::size_t{N::value}>( i, std::forward<F>(f) );
}
#undef BOOST_MP11_CONSTEXPR14
#undef BOOST_MP11_UNREACHABLE_DEFAULT
} // namespace mp11
} // namespace boost
#endif // #ifndef BOOST_MP11_DETAIL_MP_WITH_INDEX_HPP_INCLUDED

View File

@@ -0,0 +1,160 @@
#ifndef BOOST_MP11_DETAIL_MPL_COMMON_HPP_INCLUDED
#define BOOST_MP11_DETAIL_MPL_COMMON_HPP_INCLUDED
// Copyright 2017, 2019 Peter Dimov.
//
// 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/list.hpp>
#include <boost/mp11/algorithm.hpp>
namespace boost
{
namespace mpl
{
struct forward_iterator_tag;
namespace aux
{
struct mp11_tag {};
template<class L> struct mp11_iterator
{
using category = forward_iterator_tag;
using type = mp11::mp_first<L>;
using next = mp11_iterator<mp11::mp_rest<L>>;
};
} // namespace aux
// at
template< typename Tag > struct at_impl;
template<> struct at_impl<aux::mp11_tag>
{
template<class L, class I> struct apply
{
using type = mp11::mp_at<L, I>;
};
};
// back
template< typename Tag > struct back_impl;
template<> struct back_impl<aux::mp11_tag>
{
template<class L> struct apply
{
using N = mp11::mp_size<L>;
using type = mp11::mp_at_c<L, N::value - 1>;
};
};
// begin
template< typename Tag > struct begin_impl;
template<> struct begin_impl<aux::mp11_tag>
{
template<class L> struct apply
{
using type = aux::mp11_iterator<L>;
};
};
// clear
template< typename Tag > struct clear_impl;
template<> struct clear_impl<aux::mp11_tag>
{
template<class L> struct apply
{
using type = mp11::mp_clear<L>;
};
};
// end
template< typename Tag > struct end_impl;
template<> struct end_impl<aux::mp11_tag>
{
template<class L> struct apply
{
using type = aux::mp11_iterator<mp11::mp_clear<L>>;
};
};
// front
template< typename Tag > struct front_impl;
template<> struct front_impl<aux::mp11_tag>
{
template<class L> struct apply
{
using type = mp11::mp_front<L>;
};
};
// pop_front
template< typename Tag > struct pop_front_impl;
template<> struct pop_front_impl<aux::mp11_tag>
{
template<class L> struct apply
{
using type = mp11::mp_pop_front<L>;
};
};
// push_back
template< typename Tag > struct push_back_impl;
template<> struct push_back_impl<aux::mp11_tag>
{
template<class L, class T> struct apply
{
using type = mp11::mp_push_back<L, T>;
};
};
// push_front
template< typename Tag > struct push_front_impl;
template<> struct push_front_impl<aux::mp11_tag>
{
template<class L, class T> struct apply
{
using type = mp11::mp_push_front<L, T>;
};
};
// size
template< typename Tag > struct size_impl;
template<> struct size_impl<aux::mp11_tag>
{
template<class L> struct apply
{
using type = mp11::mp_size<L>;
};
};
} // namespace mpl
} // namespace boost
#endif // #ifndef BOOST_MP11_DETAIL_MPL_COMMON_HPP_INCLUDED

View File

@@ -0,0 +1,222 @@
#ifndef BOOST_MP11_FUNCTION_HPP_INCLUDED
#define BOOST_MP11_FUNCTION_HPP_INCLUDED
// Copyright 2015-2019 Peter Dimov.
//
// 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/integral.hpp>
#include <boost/mp11/utility.hpp>
#include <boost/mp11/detail/mp_list.hpp>
#include <boost/mp11/detail/mp_count.hpp>
#include <boost/mp11/detail/mp_plus.hpp>
#include <boost/mp11/detail/mp_min_element.hpp>
#include <boost/mp11/detail/mp_void.hpp>
#include <boost/mp11/detail/config.hpp>
#include <type_traits>
namespace boost
{
namespace mp11
{
// mp_void<T...>
// in detail/mp_void.hpp
// mp_and<T...>
#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1910 )
namespace detail
{
template<class... T> struct mp_and_impl;
} // namespace detail
template<class... T> using mp_and = mp_to_bool< typename detail::mp_and_impl<T...>::type >;
namespace detail
{
template<> struct mp_and_impl<>
{
using type = mp_true;
};
template<class T> struct mp_and_impl<T>
{
using type = T;
};
template<class T1, class... T> struct mp_and_impl<T1, T...>
{
using type = mp_eval_if< mp_not<T1>, T1, mp_and, T... >;
};
} // namespace detail
#else
namespace detail
{
template<class L, class E = void> struct mp_and_impl
{
using type = mp_false;
};
template<class... T> struct mp_and_impl< mp_list<T...>, mp_void<mp_if<T, void>...> >
{
using type = mp_true;
};
} // namespace detail
template<class... T> using mp_and = typename detail::mp_and_impl<mp_list<T...>>::type;
#endif
// mp_all<T...>
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86355
#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 ) || BOOST_MP11_WORKAROUND( BOOST_MP11_GCC, != 0 )
template<class... T> using mp_all = mp_bool< mp_count_if< mp_list<T...>, mp_not >::value == 0 >;
#else
template<class... T> using mp_all = mp_bool< mp_count< mp_list<mp_to_bool<T>...>, mp_false >::value == 0 >;
#endif
// mp_or<T...>
namespace detail
{
template<class... T> struct mp_or_impl;
} // namespace detail
template<class... T> using mp_or = mp_to_bool< typename detail::mp_or_impl<T...>::type >;
namespace detail
{
template<> struct mp_or_impl<>
{
using type = mp_false;
};
template<class T> struct mp_or_impl<T>
{
using type = T;
};
template<class T1, class... T> struct mp_or_impl<T1, T...>
{
using type = mp_eval_if< T1, T1, mp_or, T... >;
};
} // namespace detail
// mp_any<T...>
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86356
#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 ) || BOOST_MP11_WORKAROUND( BOOST_MP11_GCC, != 0 )
template<class... T> using mp_any = mp_bool< mp_count_if< mp_list<T...>, mp_to_bool >::value != 0 >;
#else
template<class... T> using mp_any = mp_bool< mp_count< mp_list<mp_to_bool<T>...>, mp_true >::value != 0 >;
#endif
// mp_same<T...>
namespace detail
{
template<class... T> struct mp_same_impl;
template<> struct mp_same_impl<>
{
using type = mp_true;
};
template<class T1, class... T> struct mp_same_impl<T1, T...>
{
using type = mp_bool< mp_count<mp_list<T...>, T1>::value == sizeof...(T) >;
};
} // namespace detail
template<class... T> using mp_same = typename detail::mp_same_impl<T...>::type;
// mp_similar<T...>
namespace detail
{
template<class... T> struct mp_similar_impl;
template<> struct mp_similar_impl<>
{
using type = mp_true;
};
template<class T> struct mp_similar_impl<T>
{
using type = mp_true;
};
template<class T> struct mp_similar_impl<T, T>
{
using type = mp_true;
};
template<class T1, class T2> struct mp_similar_impl<T1, T2>
{
using type = mp_false;
};
template<template<class...> class L, class... T1, class... T2> struct mp_similar_impl<L<T1...>, L<T2...>>
{
using type = mp_true;
};
template<template<class...> class L, class... T> struct mp_similar_impl<L<T...>, L<T...>>
{
using type = mp_true;
};
template<class T1, class T2, class T3, class... T> struct mp_similar_impl<T1, T2, T3, T...>
{
using type = mp_all< typename mp_similar_impl<T1, T2>::type, typename mp_similar_impl<T1, T3>::type, typename mp_similar_impl<T1, T>::type... >;
};
} // namespace detail
template<class... T> using mp_similar = typename detail::mp_similar_impl<T...>::type;
#if BOOST_MP11_GCC
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wsign-compare"
#endif
// mp_less<T1, T2>
template<class T1, class T2> using mp_less = mp_bool<(T1::value < 0 && T2::value >= 0) || ((T1::value < T2::value) && !(T1::value >= 0 && T2::value < 0))>;
#if BOOST_MP11_GCC
# pragma GCC diagnostic pop
#endif
// mp_min<T...>
template<class T1, class... T> using mp_min = mp_min_element<mp_list<T1, T...>, mp_less>;
// mp_max<T...>
template<class T1, class... T> using mp_max = mp_max_element<mp_list<T1, T...>, mp_less>;
} // namespace mp11
} // namespace boost
#endif // #ifndef BOOST_MP11_FUNCTION_HPP_INCLUDED

View File

@@ -0,0 +1,112 @@
#ifndef BOOST_MP11_INTEGER_SEQUENCE_HPP_INCLUDED
#define BOOST_MP11_INTEGER_SEQUENCE_HPP_INCLUDED
// Copyright 2015, 2017, 2019 Peter Dimov.
//
// 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/version.hpp>
#include <cstddef>
#if defined(__has_builtin)
# if __has_builtin(__make_integer_seq)
# define BOOST_MP11_HAS_MAKE_INTEGER_SEQ
# endif
#endif
namespace boost
{
namespace mp11
{
// integer_sequence
template<class T, T... I> struct integer_sequence
{
};
#if defined(BOOST_MP11_HAS_MAKE_INTEGER_SEQ)
template<class T, T N> using make_integer_sequence = __make_integer_seq<integer_sequence, T, N>;
#else
// detail::make_integer_sequence_impl
namespace detail
{
// iseq_if_c
template<bool C, class T, class E> struct iseq_if_c_impl;
template<class T, class E> struct iseq_if_c_impl<true, T, E>
{
using type = T;
};
template<class T, class E> struct iseq_if_c_impl<false, T, E>
{
using type = E;
};
template<bool C, class T, class E> using iseq_if_c = typename iseq_if_c_impl<C, T, E>::type;
// iseq_identity
template<class T> struct iseq_identity
{
using type = T;
};
template<class S1, class S2> struct append_integer_sequence;
template<class T, T... I, T... J> struct append_integer_sequence<integer_sequence<T, I...>, integer_sequence<T, J...>>
{
using type = integer_sequence< T, I..., ( J + sizeof...(I) )... >;
};
template<class T, T N> struct make_integer_sequence_impl;
template<class T, T N> struct make_integer_sequence_impl_
{
private:
static_assert( N >= 0, "make_integer_sequence<T, N>: N must not be negative" );
static T const M = N / 2;
static T const R = N % 2;
using S1 = typename make_integer_sequence_impl<T, M>::type;
using S2 = typename append_integer_sequence<S1, S1>::type;
using S3 = typename make_integer_sequence_impl<T, R>::type;
using S4 = typename append_integer_sequence<S2, S3>::type;
public:
using type = S4;
};
template<class T, T N> struct make_integer_sequence_impl: iseq_if_c<N == 0, iseq_identity<integer_sequence<T>>, iseq_if_c<N == 1, iseq_identity<integer_sequence<T, 0>>, make_integer_sequence_impl_<T, N> > >
{
};
} // namespace detail
// make_integer_sequence
template<class T, T N> using make_integer_sequence = typename detail::make_integer_sequence_impl<T, N>::type;
#endif // defined(BOOST_MP11_HAS_MAKE_INTEGER_SEQ)
// index_sequence
template<std::size_t... I> using index_sequence = integer_sequence<std::size_t, I...>;
// make_index_sequence
template<std::size_t N> using make_index_sequence = make_integer_sequence<std::size_t, N>;
// index_sequence_for
template<class... T> using index_sequence_for = make_integer_sequence<std::size_t, sizeof...(T)>;
} // namespace mp11
} // namespace boost
#endif // #ifndef BOOST_MP11_INTEGER_SEQUENCE_HPP_INCLUDED

View File

@@ -0,0 +1,42 @@
#ifndef BOOST_MP11_INTEGRAL_HPP_INCLUDED
#define BOOST_MP11_INTEGRAL_HPP_INCLUDED
// Copyright 2015 Peter Dimov.
//
// 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/version.hpp>
#include <boost/mp11/detail/mp_value.hpp>
#include <type_traits>
#include <cstddef>
namespace boost
{
namespace mp11
{
// mp_bool
template<bool B> using mp_bool = std::integral_constant<bool, B>;
using mp_true = mp_bool<true>;
using mp_false = mp_bool<false>;
// mp_to_bool
template<class T> using mp_to_bool = mp_bool<static_cast<bool>( T::value )>;
// mp_not<T>
template<class T> using mp_not = mp_bool< !T::value >;
// mp_int
template<int I> using mp_int = std::integral_constant<int, I>;
// mp_size_t
template<std::size_t N> using mp_size_t = std::integral_constant<std::size_t, N>;
} // namespace mp11
} // namespace boost
#endif // #ifndef BOOST_MP11_INTEGRAL_HPP_INCLUDED

View File

@@ -0,0 +1,472 @@
#ifndef BOOST_MP11_LIST_HPP_INCLUDED
#define BOOST_MP11_LIST_HPP_INCLUDED
// Copyright 2015-2023 Peter Dimov.
//
// 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/integral.hpp>
#include <boost/mp11/detail/mp_list.hpp>
#include <boost/mp11/detail/mp_list_v.hpp>
#include <boost/mp11/detail/mp_is_list.hpp>
#include <boost/mp11/detail/mp_is_value_list.hpp>
#include <boost/mp11/detail/mp_front.hpp>
#include <boost/mp11/detail/mp_rename.hpp>
#include <boost/mp11/detail/mp_append.hpp>
#include <boost/mp11/detail/config.hpp>
#include <type_traits>
namespace boost
{
namespace mp11
{
// mp_list<T...>
// in detail/mp_list.hpp
// mp_list_c<T, I...>
template<class T, T... I> using mp_list_c = mp_list<std::integral_constant<T, I>...>;
// mp_list_v<A...>
// in detail/mp_list_v.hpp
// mp_is_list<L>
// in detail/mp_is_list.hpp
// mp_is_value_list<L>
// in detail/mp_is_value_list.hpp
// mp_size<L>
namespace detail
{
template<class L> struct mp_size_impl
{
// An error "no type named 'type'" here means that the argument to mp_size is not a list
};
template<template<class...> class L, class... T> struct mp_size_impl<L<T...>>
{
using type = mp_size_t<sizeof...(T)>;
};
#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO)
template<template<auto...> class L, auto... A> struct mp_size_impl<L<A...>>
{
using type = mp_size_t<sizeof...(A)>;
};
#endif
} // namespace detail
template<class L> using mp_size = typename detail::mp_size_impl<L>::type;
// mp_empty<L>
template<class L> using mp_empty = mp_bool< mp_size<L>::value == 0 >;
// mp_assign<L1, L2>
namespace detail
{
template<class L1, class L2> struct mp_assign_impl
{
// An error "no type named 'type'" here means that the arguments to mp_assign aren't lists
};
template<template<class...> class L1, class... T, template<class...> class L2, class... U> struct mp_assign_impl<L1<T...>, L2<U...>>
{
using type = L1<U...>;
};
#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO)
template<template<auto...> class L1, auto... A, template<class...> class L2, class... U> struct mp_assign_impl<L1<A...>, L2<U...>>
{
using type = L1<U::value...>;
};
template<template<class...> class L1, class... T, template<auto...> class L2, auto... B> struct mp_assign_impl<L1<T...>, L2<B...>>
{
using type = L1<mp_value<B>...>;
};
template<template<auto...> class L1, auto... A, template<auto...> class L2, auto... B> struct mp_assign_impl<L1<A...>, L2<B...>>
{
using type = L1<B...>;
};
#endif
} // namespace detail
template<class L1, class L2> using mp_assign = typename detail::mp_assign_impl<L1, L2>::type;
// mp_clear<L>
template<class L> using mp_clear = mp_assign<L, mp_list<>>;
// mp_front<L>
// in detail/mp_front.hpp
// mp_pop_front<L>
namespace detail
{
template<class L> struct mp_pop_front_impl
{
// An error "no type named 'type'" here means that the argument to mp_pop_front
// is either not a list, or is an empty list
};
template<template<class...> class L, class T1, class... T> struct mp_pop_front_impl<L<T1, T...>>
{
using type = L<T...>;
};
#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO)
template<template<auto...> class L, auto A1, auto... A> struct mp_pop_front_impl<L<A1, A...>>
{
using type = L<A...>;
};
#endif
} // namespace detail
template<class L> using mp_pop_front = typename detail::mp_pop_front_impl<L>::type;
// mp_first<L>
template<class L> using mp_first = mp_front<L>;
// mp_rest<L>
template<class L> using mp_rest = mp_pop_front<L>;
// mp_second<L>
namespace detail
{
template<class L> struct mp_second_impl
{
// An error "no type named 'type'" here means that the argument to mp_second
// is either not a list, or has fewer than two elements
};
template<template<class...> class L, class T1, class T2, class... T> struct mp_second_impl<L<T1, T2, T...>>
{
using type = T2;
};
#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO)
template<template<auto...> class L, auto A1, auto A2, auto... A> struct mp_second_impl<L<A1, A2, A...>>
{
using type = mp_value<A2>;
};
#endif
} // namespace detail
template<class L> using mp_second = typename detail::mp_second_impl<L>::type;
// mp_third<L>
namespace detail
{
template<class L> struct mp_third_impl
{
// An error "no type named 'type'" here means that the argument to mp_third
// is either not a list, or has fewer than three elements
};
template<template<class...> class L, class T1, class T2, class T3, class... T> struct mp_third_impl<L<T1, T2, T3, T...>>
{
using type = T3;
};
#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO)
template<template<auto...> class L, auto A1, auto A2, auto A3, auto... A> struct mp_third_impl<L<A1, A2, A3, A...>>
{
using type = mp_value<A3>;
};
#endif
} // namespace detail
template<class L> using mp_third = typename detail::mp_third_impl<L>::type;
// mp_push_front<L, T...>
namespace detail
{
template<class L, class... T> struct mp_push_front_impl
{
// An error "no type named 'type'" here means that the first argument to mp_push_front is not a list
};
template<template<class...> class L, class... U, class... T> struct mp_push_front_impl<L<U...>, T...>
{
using type = L<T..., U...>;
};
#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO)
template<template<auto...> class L, auto... A, class... T> struct mp_push_front_impl<L<A...>, T...>
{
using type = L<T::value..., A...>;
};
#endif
} // namespace detail
template<class L, class... T> using mp_push_front = typename detail::mp_push_front_impl<L, T...>::type;
// mp_push_back<L, T...>
namespace detail
{
template<class L, class... T> struct mp_push_back_impl
{
// An error "no type named 'type'" here means that the first argument to mp_push_back is not a list
};
template<template<class...> class L, class... U, class... T> struct mp_push_back_impl<L<U...>, T...>
{
using type = L<U..., T...>;
};
#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO)
template<template<auto...> class L, auto... A, class... T> struct mp_push_back_impl<L<A...>, T...>
{
using type = L<A..., T::value...>;
};
#endif
} // namespace detail
template<class L, class... T> using mp_push_back = typename detail::mp_push_back_impl<L, T...>::type;
// mp_rename<L, B>
// mp_apply<F, L>
// mp_apply_q<Q, L>
// in detail/mp_rename.hpp
// mp_rename_v<L, B>
#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO)
namespace detail
{
template<class L, template<auto...> class B> struct mp_rename_v_impl
{
// An error "no type named 'type'" here means that the first argument to mp_rename_v is not a list
};
template<template<class...> class L, class... T, template<auto...> class B> struct mp_rename_v_impl<L<T...>, B>
{
using type = B<T::value...>;
};
template<template<auto...> class L, auto... A, template<auto...> class B> struct mp_rename_v_impl<L<A...>, B>
{
using type = B<A...>;
};
} // namespace detail
template<class L, template<auto...> class B> using mp_rename_v = typename detail::mp_rename_v_impl<L, B>::type;
#endif
// mp_replace_front<L, T>
namespace detail
{
template<class L, class T> struct mp_replace_front_impl
{
// An error "no type named 'type'" here means that the first argument to mp_replace_front
// is either not a list, or is an empty list
};
template<template<class...> class L, class U1, class... U, class T> struct mp_replace_front_impl<L<U1, U...>, T>
{
using type = L<T, U...>;
};
#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO)
template<template<auto...> class L, auto A1, auto... A, class T> struct mp_replace_front_impl<L<A1, A...>, T>
{
using type = L<T::value, A...>;
};
#endif
} // namespace detail
template<class L, class T> using mp_replace_front = typename detail::mp_replace_front_impl<L, T>::type;
// mp_replace_first<L, T>
template<class L, class T> using mp_replace_first = typename detail::mp_replace_front_impl<L, T>::type;
// mp_replace_second<L, T>
namespace detail
{
template<class L, class T> struct mp_replace_second_impl
{
// An error "no type named 'type'" here means that the first argument to mp_replace_second
// is either not a list, or has fewer than two elements
};
template<template<class...> class L, class U1, class U2, class... U, class T> struct mp_replace_second_impl<L<U1, U2, U...>, T>
{
using type = L<U1, T, U...>;
};
#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO)
template<template<auto...> class L, auto A1, auto A2, auto... A, class T> struct mp_replace_second_impl<L<A1, A2, A...>, T>
{
using type = L<A1, T::value, A...>;
};
#endif
} // namespace detail
template<class L, class T> using mp_replace_second = typename detail::mp_replace_second_impl<L, T>::type;
// mp_replace_third<L, T>
namespace detail
{
template<class L, class T> struct mp_replace_third_impl
{
// An error "no type named 'type'" here means that the first argument to mp_replace_third
// is either not a list, or has fewer than three elements
};
template<template<class...> class L, class U1, class U2, class U3, class... U, class T> struct mp_replace_third_impl<L<U1, U2, U3, U...>, T>
{
using type = L<U1, U2, T, U...>;
};
#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO)
template<template<auto...> class L, auto A1, auto A2, auto A3, auto... A, class T> struct mp_replace_third_impl<L<A1, A2, A3, A...>, T>
{
using type = L<A1, A2, T::value, A...>;
};
#endif
} // namespace detail
template<class L, class T> using mp_replace_third = typename detail::mp_replace_third_impl<L, T>::type;
// mp_transform_front<L, F>
namespace detail
{
template<class L, template<class...> class F> struct mp_transform_front_impl
{
// An error "no type named 'type'" here means that the first argument to mp_transform_front
// is either not a list, or is an empty list
};
template<template<class...> class L, class U1, class... U, template<class...> class F> struct mp_transform_front_impl<L<U1, U...>, F>
{
using type = L<F<U1>, U...>;
};
#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO)
template<template<auto...> class L, auto A1, auto... A, template<class...> class F> struct mp_transform_front_impl<L<A1, A...>, F>
{
using type = L<F<mp_value<A1>>::value, A...>;
};
#endif
} // namespace detail
template<class L, template<class...> class F> using mp_transform_front = typename detail::mp_transform_front_impl<L, F>::type;
template<class L, class Q> using mp_transform_front_q = mp_transform_front<L, Q::template fn>;
// mp_transform_first<L, F>
template<class L, template<class...> class F> using mp_transform_first = typename detail::mp_transform_front_impl<L, F>::type;
template<class L, class Q> using mp_transform_first_q = mp_transform_first<L, Q::template fn>;
// mp_transform_second<L, F>
namespace detail
{
template<class L, template<class...> class F> struct mp_transform_second_impl
{
// An error "no type named 'type'" here means that the first argument to mp_transform_second
// is either not a list, or has fewer than two elements
};
template<template<class...> class L, class U1, class U2, class... U, template<class...> class F> struct mp_transform_second_impl<L<U1, U2, U...>, F>
{
using type = L<U1, F<U2>, U...>;
};
#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO)
template<template<auto...> class L, auto A1, auto A2, auto... A, template<class...> class F> struct mp_transform_second_impl<L<A1, A2, A...>, F>
{
using type = L<A1, F<mp_value<A2>>::value, A...>;
};
#endif
} // namespace detail
template<class L, template<class...> class F> using mp_transform_second = typename detail::mp_transform_second_impl<L, F>::type;
template<class L, class Q> using mp_transform_second_q = mp_transform_second<L, Q::template fn>;
// mp_transform_third<L, F>
namespace detail
{
template<class L, template<class...> class F> struct mp_transform_third_impl
{
// An error "no type named 'type'" here means that the first argument to mp_transform_third
// is either not a list, or has fewer than three elements
};
template<template<class...> class L, class U1, class U2, class U3, class... U, template<class...> class F> struct mp_transform_third_impl<L<U1, U2, U3, U...>, F>
{
using type = L<U1, U2, F<U3>, U...>;
};
#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO)
template<template<auto...> class L, auto A1, auto A2, auto A3, auto... A, template<class...> class F> struct mp_transform_third_impl<L<A1, A2, A3, A...>, F>
{
using type = L<A1, A2, F<mp_value<A3>>::value, A...>;
};
#endif
} // namespace detail
template<class L, template<class...> class F> using mp_transform_third = typename detail::mp_transform_third_impl<L, F>::type;
template<class L, class Q> using mp_transform_third_q = mp_transform_third<L, Q::template fn>;
} // namespace mp11
} // namespace boost
#endif // #ifndef BOOST_MP11_LIST_HPP_INCLUDED

View File

@@ -0,0 +1,119 @@
#ifndef BOOST_MP11_MAP_HPP_INCLUDED
#define BOOST_MP11_MAP_HPP_INCLUDED
// Copyright 2015-2017 Peter Dimov.
//
// 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/mp_map_find.hpp>
#include <boost/mp11/list.hpp>
#include <boost/mp11/integral.hpp>
#include <boost/mp11/utility.hpp>
#include <boost/mp11/algorithm.hpp>
#include <boost/mp11/function.hpp>
#include <boost/mp11/set.hpp>
#include <type_traits>
namespace boost
{
namespace mp11
{
// mp_map_contains<M, K>
template<class M, class K> using mp_map_contains = mp_not<std::is_same<mp_map_find<M, K>, void>>;
// mp_map_insert<M, T>
template<class M, class T> using mp_map_insert = mp_if< mp_map_contains<M, mp_first<T>>, M, mp_push_back<M, T> >;
// mp_map_replace<M, T>
namespace detail
{
template<class M, class T> struct mp_map_replace_impl;
template<template<class...> class M, class... U, class T> struct mp_map_replace_impl<M<U...>, T>
{
using K = mp_first<T>;
// mp_replace_if is inlined here using a struct _f because of msvc-14.0
template<class V> struct _f { using type = mp_if< std::is_same<mp_first<V>, K>, T, V >; };
using type = mp_if< mp_map_contains<M<U...>, K>, M<typename _f<U>::type...>, M<U..., T> >;
};
} // namespace detail
template<class M, class T> using mp_map_replace = typename detail::mp_map_replace_impl<M, T>::type;
// mp_map_update<M, T, F>
namespace detail
{
template<class M, class T, template<class...> class F> struct mp_map_update_impl
{
template<class U> using _f = std::is_same<mp_first<T>, mp_first<U>>;
// _f3<L<X, Y...>> -> L<X, F<X, Y...>>
template<class L> using _f3 = mp_assign<L, mp_list<mp_first<L>, mp_rename<L, F> > >;
using type = mp_if< mp_map_contains<M, mp_first<T>>, mp_transform_if<_f, _f3, M>, mp_push_back<M, T> >;
};
} // namespace detail
template<class M, class T, template<class...> class F> using mp_map_update = typename detail::mp_map_update_impl<M, T, F>::type;
template<class M, class T, class Q> using mp_map_update_q = mp_map_update<M, T, Q::template fn>;
// mp_map_erase<M, K>
namespace detail
{
template<class M, class K> struct mp_map_erase_impl
{
template<class T> using _f = std::is_same<mp_first<T>, K>;
using type = mp_remove_if<M, _f>;
};
} // namespace detail
template<class M, class K> using mp_map_erase = typename detail::mp_map_erase_impl<M, K>::type;
// mp_map_keys<M>
template<class M> using mp_map_keys = mp_transform<mp_first, M>;
// mp_is_map<M>
namespace detail
{
template<class L> struct mp_is_map_element: mp_false
{
};
template<template<class...> class L, class T1, class... T> struct mp_is_map_element<L<T1, T...>>: mp_true
{
};
template<class M> using mp_keys_are_set = mp_is_set<mp_map_keys<M>>;
template<class M> struct mp_is_map_impl
{
using type = mp_false;
};
template<template<class...> class M, class... T> struct mp_is_map_impl<M<T...>>
{
using type = mp_eval_if<mp_not<mp_all<mp_is_map_element<T>...>>, mp_false, mp_keys_are_set, M<T...>>;
};
} // namespace detail
template<class M> using mp_is_map = typename detail::mp_is_map_impl<M>::type;
} // namespace mp11
} // namespace boost
#endif // #ifndef BOOST_MP11_MAP_HPP_INCLUDED

View File

@@ -0,0 +1,14 @@
#ifndef BOOST_MP11_MPL_HPP_INCLUDED
#define BOOST_MP11_MPL_HPP_INCLUDED
// Copyright 2017, 2019 Peter Dimov.
//
// 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/mpl_list.hpp>
#include <boost/mp11/mpl_tuple.hpp>
#endif // #ifndef BOOST_MP11_MPL_HPP_INCLUDED

View File

@@ -0,0 +1,28 @@
#ifndef BOOST_MP11_MPL_LIST_HPP_INCLUDED
#define BOOST_MP11_MPL_LIST_HPP_INCLUDED
// Copyright 2017, 2019 Peter Dimov.
//
// 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/mpl_common.hpp>
namespace boost
{
namespace mpl
{
template< typename Sequence > struct sequence_tag;
template<class... T> struct sequence_tag<mp11::mp_list<T...>>
{
using type = aux::mp11_tag;
};
} // namespace mpl
} // namespace boost
#endif // #ifndef BOOST_MP11_MPL_LIST_HPP_INCLUDED

View File

@@ -0,0 +1,29 @@
#ifndef BOOST_MP11_MPL_TUPLE_HPP_INCLUDED
#define BOOST_MP11_MPL_TUPLE_HPP_INCLUDED
// Copyright 2017, 2019 Peter Dimov.
//
// 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/mpl_common.hpp>
#include <tuple>
namespace boost
{
namespace mpl
{
template< typename Sequence > struct sequence_tag;
template<class... T> struct sequence_tag<std::tuple<T...>>
{
using type = aux::mp11_tag;
};
} // namespace mpl
} // namespace boost
#endif // #ifndef BOOST_MP11_MPL_TUPLE_HPP_INCLUDED

View File

@@ -0,0 +1,188 @@
#ifndef BOOST_MP11_SET_HPP_INCLUDED
#define BOOST_MP11_SET_HPP_INCLUDED
// Copyright 2015, 2019 Peter Dimov.
//
// 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/function.hpp>
#include <boost/mp11/detail/mp_list.hpp>
#include <boost/mp11/detail/mp_append.hpp>
#include <boost/mp11/detail/mp_copy_if.hpp>
#include <boost/mp11/detail/mp_remove_if.hpp>
#include <boost/mp11/detail/mp_is_list.hpp>
#include <type_traits>
namespace boost
{
namespace mp11
{
// mp_set_contains<S, V>
namespace detail
{
template<class S, class V> struct mp_set_contains_impl
{
};
template<template<class...> class L, class... T, class V> struct mp_set_contains_impl<L<T...>, V>
{
using type = mp_to_bool<std::is_base_of<mp_identity<V>, mp_inherit<mp_identity<T>...> > >;
};
} // namespace detail
template<class S, class V> using mp_set_contains = typename detail::mp_set_contains_impl<S, V>::type;
// mp_set_push_back<S, T...>
namespace detail
{
template<class S, class... T> struct mp_set_push_back_impl
{
};
template<template<class...> class L, class... U> struct mp_set_push_back_impl<L<U...>>
{
using type = L<U...>;
};
template<template<class...> class L, class... U, class T1, class... T> struct mp_set_push_back_impl<L<U...>, T1, T...>
{
using S = mp_if<mp_set_contains<L<U...>, T1>, L<U...>, L<U..., T1>>;
using type = typename mp_set_push_back_impl<S, T...>::type;
};
} // namespace detail
template<class S, class... T> using mp_set_push_back = typename detail::mp_set_push_back_impl<S, T...>::type;
// mp_set_push_front<S, T...>
namespace detail
{
template<class S, class... T> struct mp_set_push_front_impl
{
};
template<template<class...> class L, class... U> struct mp_set_push_front_impl<L<U...>>
{
using type = L<U...>;
};
template<template<class...> class L, class... U, class T1> struct mp_set_push_front_impl<L<U...>, T1>
{
using type = mp_if<mp_set_contains<L<U...>, T1>, L<U...>, L<T1, U...>>;
};
template<template<class...> class L, class... U, class T1, class... T> struct mp_set_push_front_impl<L<U...>, T1, T...>
{
using S = typename mp_set_push_front_impl<L<U...>, T...>::type;
using type = typename mp_set_push_front_impl<S, T1>::type;
};
} // namespace detail
template<class S, class... T> using mp_set_push_front = typename detail::mp_set_push_front_impl<S, T...>::type;
// mp_is_set<S>
namespace detail
{
template<class S> struct mp_is_set_impl
{
using type = mp_false;
};
template<template<class...> class L, class... T> struct mp_is_set_impl<L<T...>>
{
using type = mp_to_bool<std::is_same<mp_list<T...>, mp_set_push_back<mp_list<>, T...> > >;
};
} // namespace detail
template<class S> using mp_is_set = typename detail::mp_is_set_impl<S>::type;
// mp_set_union<L...>
namespace detail
{
template<class... L> struct mp_set_union_impl
{
};
template<> struct mp_set_union_impl<>
{
using type = mp_list<>;
};
template<template<class...> class L, class... T> struct mp_set_union_impl<L<T...>>
{
using type = L<T...>;
};
template<template<class...> class L1, class... T1, template<class...> class L2, class... T2> struct mp_set_union_impl<L1<T1...>, L2<T2...>>
{
using type = mp_set_push_back<L1<T1...>, T2...>;
};
template<class L1, class... L> using mp_set_union_ = typename mp_set_union_impl<L1, mp_append<mp_list<>, L...>>::type;
template<class L1, class L2, class L3, class... L> struct mp_set_union_impl<L1, L2, L3, L...>: mp_defer<mp_set_union_, L1, L2, L3, L...>
{
};
} // namespace detail
template<class... L> using mp_set_union = typename detail::mp_set_union_impl<L...>::type;
// mp_set_intersection<S...>
namespace detail
{
template<class... S> struct in_all_sets
{
template<class T> using fn = mp_all< mp_set_contains<S, T>... >;
};
template<class L, class... S> using mp_set_intersection_ = mp_if< mp_all<mp_is_list<S>...>, mp_copy_if_q<L, detail::in_all_sets<S...>> >;
template<class... S> struct mp_set_intersection_impl
{
};
template<> struct mp_set_intersection_impl<>
{
using type = mp_list<>;
};
template<class L, class... S> struct mp_set_intersection_impl<L, S...>: mp_defer<mp_set_intersection_, L, S...>
{
};
} // namespace detail
template<class... S> using mp_set_intersection = typename detail::mp_set_intersection_impl<S...>::type;
// mp_set_difference<L, S...>
namespace detail
{
template<class... S> struct in_any_set
{
template<class T> using fn = mp_any< mp_set_contains<S, T>... >;
};
} // namespace detail
template<class L, class... S> using mp_set_difference = mp_if< mp_all<mp_is_list<S>...>, mp_remove_if_q<L, detail::in_any_set<S...>> >;
} // namespace mp11
} // namespace boost
#endif // #ifndef BOOST_MP11_SET_HPP_INCLUDED

View File

@@ -0,0 +1,183 @@
#ifndef BOOST_MP11_TUPLE_HPP_INCLUDED
#define BOOST_MP11_TUPLE_HPP_INCLUDED
// Copyright 2015-2020 Peter Dimov.
//
// 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/integer_sequence.hpp>
#include <boost/mp11/list.hpp>
#include <boost/mp11/function.hpp>
#include <boost/mp11/detail/config.hpp>
#include <tuple>
#include <utility>
#include <type_traits>
#include <cstddef>
#if BOOST_MP11_MSVC
# pragma warning( push )
# pragma warning( disable: 4100 ) // unreferenced formal parameter 'tp'
#endif
namespace boost
{
namespace mp11
{
// tuple_apply
namespace detail
{
using std::get;
template<class F, class Tp, std::size_t... J> BOOST_MP11_CONSTEXPR auto tuple_apply_impl( F && f, Tp && tp, integer_sequence<std::size_t, J...> )
-> decltype( std::forward<F>(f)( get<J>(std::forward<Tp>(tp))... ) )
{
return std::forward<F>(f)( get<J>(std::forward<Tp>(tp))... );
}
} // namespace detail
template<class F, class Tp,
class Seq = make_index_sequence<std::tuple_size<typename std::remove_reference<Tp>::type>::value>>
BOOST_MP11_CONSTEXPR auto tuple_apply( F && f, Tp && tp )
-> decltype( detail::tuple_apply_impl( std::forward<F>(f), std::forward<Tp>(tp), Seq() ) )
{
return detail::tuple_apply_impl( std::forward<F>(f), std::forward<Tp>(tp), Seq() );
}
// construct_from_tuple
namespace detail
{
template<class T, class Tp, std::size_t... J> BOOST_MP11_CONSTEXPR T construct_from_tuple_impl( Tp && tp, integer_sequence<std::size_t, J...> )
{
return T( get<J>(std::forward<Tp>(tp))... );
}
} // namespace detail
template<class T, class Tp,
class Seq = make_index_sequence<std::tuple_size<typename std::remove_reference<Tp>::type>::value>>
BOOST_MP11_CONSTEXPR T construct_from_tuple( Tp && tp )
{
return detail::construct_from_tuple_impl<T>( std::forward<Tp>(tp), Seq() );
}
// tuple_for_each
namespace detail
{
template<class Tp, std::size_t... J, class F> BOOST_MP11_CONSTEXPR F tuple_for_each_impl( Tp && tp, integer_sequence<std::size_t, J...>, F && f )
{
using A = int[sizeof...(J)];
return (void)A{ ((void)f(get<J>(std::forward<Tp>(tp))), 0)... }, std::forward<F>(f);
}
template<class Tp, class F> BOOST_MP11_CONSTEXPR F tuple_for_each_impl( Tp && /*tp*/, integer_sequence<std::size_t>, F && f )
{
return std::forward<F>(f);
}
} // namespace detail
template<class Tp, class F> BOOST_MP11_CONSTEXPR F tuple_for_each( Tp && tp, F && f )
{
using seq = make_index_sequence<std::tuple_size<typename std::remove_reference<Tp>::type>::value>;
return detail::tuple_for_each_impl( std::forward<Tp>(tp), seq(), std::forward<F>(f) );
}
// tuple_transform
namespace detail
{
// std::forward_as_tuple is not constexpr in C++11 or libstdc++ 5.x
template<class... T> BOOST_MP11_CONSTEXPR auto tp_forward_r( T&&... t ) -> std::tuple<T&&...>
{
return std::tuple<T&&...>( std::forward<T>( t )... );
}
template<class... T> BOOST_MP11_CONSTEXPR auto tp_forward_v( T&&... t ) -> std::tuple<T...>
{
return std::tuple<T...>( std::forward<T>( t )... );
}
template<std::size_t J, class... Tp>
BOOST_MP11_CONSTEXPR auto tp_extract( Tp&&... tp )
-> decltype( tp_forward_r( get<J>( std::forward<Tp>( tp ) )... ) )
{
return tp_forward_r( get<J>( std::forward<Tp>( tp ) )... );
}
#if !BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1900 )
template<class F, class... Tp, std::size_t... J>
BOOST_MP11_CONSTEXPR auto tuple_transform_impl( integer_sequence<std::size_t, J...>, F const& f, Tp&&... tp )
-> decltype( tp_forward_v( tuple_apply( f, tp_extract<J>( std::forward<Tp>(tp)... ) )... ) )
{
return tp_forward_v( tuple_apply( f, tp_extract<J>( std::forward<Tp>(tp)... ) )... );
}
#else
template<class F, class Tp1, std::size_t... J>
BOOST_MP11_CONSTEXPR auto tuple_transform_impl( integer_sequence<std::size_t, J...>, F const& f, Tp1&& tp1 )
-> decltype( tp_forward_v( f( get<J>( std::forward<Tp1>(tp1) ) )... ) )
{
return tp_forward_v( f( get<J>( std::forward<Tp1>(tp1) ) )... );
}
template<class F, class Tp1, class Tp2, std::size_t... J>
BOOST_MP11_CONSTEXPR auto tuple_transform_impl( integer_sequence<std::size_t, J...>, F const& f, Tp1&& tp1, Tp2&& tp2 )
-> decltype( tp_forward_v( f( get<J>( std::forward<Tp1>(tp1) ), get<J>( std::forward<Tp2>(tp2) ) )... ) )
{
return tp_forward_v( f( get<J>( std::forward<Tp1>(tp1) ), get<J>( std::forward<Tp2>(tp2) ) )... );
}
template<class F, class Tp1, class Tp2, class Tp3, std::size_t... J>
BOOST_MP11_CONSTEXPR auto tuple_transform_impl( integer_sequence<std::size_t, J...>, F const& f, Tp1&& tp1, Tp2&& tp2, Tp3&& tp3 )
-> decltype( tp_forward_v( f( get<J>( std::forward<Tp1>(tp1) ), get<J>( std::forward<Tp2>(tp2) ), get<J>( std::forward<Tp3>(tp3) ) )... ) )
{
return tp_forward_v( f( get<J>( std::forward<Tp1>(tp1) ), get<J>( std::forward<Tp2>(tp2) ), get<J>( std::forward<Tp3>(tp3) ) )... );
}
#endif // !BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1900 )
} // namespace detail
#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1910 )
template<class F, class Tp1, class... Tp,
class Seq = make_index_sequence<std::tuple_size<typename std::remove_reference<Tp1>::type>::value>>
BOOST_MP11_CONSTEXPR auto tuple_transform( F const& f, Tp1&& tp1, Tp&&... tp )
-> decltype( detail::tuple_transform_impl( Seq(), f, std::forward<Tp1>(tp1), std::forward<Tp>(tp)... ) )
{
return detail::tuple_transform_impl( Seq(), f, std::forward<Tp1>(tp1), std::forward<Tp>(tp)... );
}
#else
template<class F, class... Tp,
class Z = mp_list<mp_size_t<std::tuple_size<typename std::remove_reference<Tp>::type>::value>...>,
class E = mp_if<mp_apply<mp_same, Z>, mp_front<Z>>,
class Seq = make_index_sequence<E::value>>
BOOST_MP11_CONSTEXPR auto tuple_transform( F const& f, Tp&&... tp )
-> decltype( detail::tuple_transform_impl( Seq(), f, std::forward<Tp>(tp)... ) )
{
return detail::tuple_transform_impl( Seq(), f, std::forward<Tp>(tp)... );
}
#endif // BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1910 )
} // namespace mp11
} // namespace boost
#if BOOST_MP11_MSVC
# pragma warning( pop )
#endif
#endif // #ifndef BOOST_TUPLE_HPP_INCLUDED

View File

@@ -0,0 +1,169 @@
#ifndef BOOST_MP11_UTILITY_HPP_INCLUDED
#define BOOST_MP11_UTILITY_HPP_INCLUDED
// Copyright 2015-2020 Peter Dimov.
//
// 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/integral.hpp>
#include <boost/mp11/detail/mp_list.hpp>
#include <boost/mp11/detail/mp_fold.hpp>
#include <boost/mp11/detail/mp_front.hpp>
#include <boost/mp11/detail/mp_rename.hpp>
#include <boost/mp11/detail/mp_defer.hpp>
#include <boost/mp11/detail/config.hpp>
namespace boost
{
namespace mp11
{
// mp_identity
template<class T> struct mp_identity
{
using type = T;
};
// mp_identity_t
template<class T> using mp_identity_t = typename mp_identity<T>::type;
// mp_inherit
template<class... T> struct mp_inherit: T... {};
// mp_if, mp_if_c
// mp_valid
// mp_defer
// moved to detail/mp_defer.hpp
// mp_eval_if, mp_eval_if_c
namespace detail
{
template<bool C, class T, template<class...> class F, class... U> struct mp_eval_if_c_impl;
template<class T, template<class...> class F, class... U> struct mp_eval_if_c_impl<true, T, F, U...>
{
using type = T;
};
template<class T, template<class...> class F, class... U> struct mp_eval_if_c_impl<false, T, F, U...>: mp_defer<F, U...>
{
};
} // namespace detail
template<bool C, class T, template<class...> class F, class... U> using mp_eval_if_c = typename detail::mp_eval_if_c_impl<C, T, F, U...>::type;
template<class C, class T, template<class...> class F, class... U> using mp_eval_if = typename detail::mp_eval_if_c_impl<static_cast<bool>(C::value), T, F, U...>::type;
template<class C, class T, class Q, class... U> using mp_eval_if_q = typename detail::mp_eval_if_c_impl<static_cast<bool>(C::value), T, Q::template fn, U...>::type;
// mp_eval_if_not
template<class C, class T, template<class...> class F, class... U> using mp_eval_if_not = mp_eval_if<mp_not<C>, T, F, U...>;
template<class C, class T, class Q, class... U> using mp_eval_if_not_q = mp_eval_if<mp_not<C>, T, Q::template fn, U...>;
// mp_eval_or
template<class T, template<class...> class F, class... U> using mp_eval_or = mp_eval_if_not<mp_valid<F, U...>, T, F, U...>;
template<class T, class Q, class... U> using mp_eval_or_q = mp_eval_or<T, Q::template fn, U...>;
// mp_valid_and_true
template<template<class...> class F, class... T> using mp_valid_and_true = mp_eval_or<mp_false, F, T...>;
template<class Q, class... T> using mp_valid_and_true_q = mp_valid_and_true<Q::template fn, T...>;
// mp_cond
// so elegant; so doesn't work
// template<class C, class T, class... E> using mp_cond = mp_eval_if<C, T, mp_cond, E...>;
namespace detail
{
template<class C, class T, class... E> struct mp_cond_impl;
} // namespace detail
template<class C, class T, class... E> using mp_cond = typename detail::mp_cond_impl<C, T, E...>::type;
namespace detail
{
template<class C, class T, class... E> using mp_cond_ = mp_eval_if<C, T, mp_cond, E...>;
template<class C, class T, class... E> struct mp_cond_impl: mp_defer<mp_cond_, C, T, E...>
{
};
} // namespace detail
// mp_quote
template<template<class...> class F> struct mp_quote
{
// the indirection through mp_defer works around the language inability
// to expand T... into a fixed parameter list of an alias template
template<class... T> using fn = typename mp_defer<F, T...>::type;
};
// mp_quote_trait
template<template<class...> class F> struct mp_quote_trait
{
template<class... T> using fn = typename F<T...>::type;
};
// mp_invoke_q
#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1900 )
namespace detail
{
template<class Q, class... T> struct mp_invoke_q_impl: mp_defer<Q::template fn, T...> {};
} // namespace detail
template<class Q, class... T> using mp_invoke_q = typename detail::mp_invoke_q_impl<Q, T...>::type;
#elif BOOST_MP11_WORKAROUND( BOOST_MP11_GCC, < 50000 )
template<class Q, class... T> using mp_invoke_q = typename mp_defer<Q::template fn, T...>::type;
#else
template<class Q, class... T> using mp_invoke_q = typename Q::template fn<T...>;
#endif
// mp_not_fn<P>
template<template<class...> class P> struct mp_not_fn
{
template<class... T> using fn = mp_not< mp_invoke_q<mp_quote<P>, T...> >;
};
template<class Q> using mp_not_fn_q = mp_not_fn<Q::template fn>;
// mp_compose
namespace detail
{
template<class L, class Q> using mp_compose_helper = mp_list< mp_apply_q<Q, L> >;
} // namespace detail
#if !BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1900 )
template<template<class...> class... F> struct mp_compose
{
template<class... T> using fn = mp_front< mp_fold<mp_list<mp_quote<F>...>, mp_list<T...>, detail::mp_compose_helper> >;
};
#endif
template<class... Q> struct mp_compose_q
{
template<class... T> using fn = mp_front< mp_fold<mp_list<Q...>, mp_list<T...>, detail::mp_compose_helper> >;
};
} // namespace mp11
} // namespace boost
#endif // #ifndef BOOST_MP11_UTILITY_HPP_INCLUDED

View File

@@ -0,0 +1,16 @@
#ifndef BOOST_MP11_VERSION_HPP_INCLUDED
#define BOOST_MP11_VERSION_HPP_INCLUDED
// Copyright 2019 Peter Dimov
//
// 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
// Same format as BOOST_VERSION:
// major * 100000 + minor * 100 + patch
#define BOOST_MP11_VERSION 108300
#endif // #ifndef BOOST_MP11_VERSION_HPP_INCLUDED

View File

@@ -0,0 +1,15 @@
#pragma once
#include <concepts>
namespace cib {
template <typename T>
concept builder_meta = requires {
typename T::builder_t;
typename T::interface_t;
{ T::uninitialized() } -> std::same_as<typename T::interface_t>;
};
template <builder_meta T> using builder_t = typename T::builder_t;
template <builder_meta T> using interface_t = typename T::interface_t;
} // namespace cib

View File

@@ -0,0 +1,8 @@
#pragma once
#include <cib/builder_meta.hpp>
namespace cib {
template <builder_meta ServiceMeta>
constinit auto service = ServiceMeta::uninitialized();
} // namespace cib

View File

@@ -0,0 +1,131 @@
#pragma once
#include <cib/builder_meta.hpp>
#include <stdx/compiler.hpp>
#include <stdx/panic.hpp>
#include <array>
#include <concepts>
#include <cstddef>
#include <utility>
namespace callback {
/**
* Builder for simple callbacks.
*
* Components can add their own callback function to this builder to be
* executed when the service is executed with the same function arguments.
*
* @tparam NumFuncs
* The number of functions currently registered with this builder.
*
* @tparam ArgTypes
* List of argument types that must be passed into the callback when it is
* invoked.
*
* @see callback::service
*/
template <int NumFuncs = 0, typename... ArgTypes> struct builder {
using func_ptr_t = void (*)(ArgTypes...);
std::array<func_ptr_t, NumFuncs> funcs{};
/**
* Add a function to be executed when the callback service is invoked.
*
* Do not call this function directly. The library will add functions
* to service builders based on a project's cib::config and cib::extend
* declarations.
*
* @return
* A version of this callback builder with the addition of func.
*
* @see cib::extend
* @see cib::nexus
*/
template <std::convertible_to<func_ptr_t>... Fs>
[[nodiscard]] constexpr auto add(Fs &&...fs) const {
builder<NumFuncs + sizeof...(Fs), ArgTypes...> cb;
auto i = std::size_t{};
while (i < NumFuncs) {
cb.funcs[i] = funcs[i];
++i;
}
((cb.funcs[i++] = std::forward<Fs>(fs)), ...);
return cb;
}
/**
* Build and return a function pointer to the implemented callback
* builder. Used by cib nexus to automatically build an initialized
* builder.
*
* Do not call directly.
*
* @tparam BuilderValue
* Struct that contains a "static constexpr auto value" field with the
* initialized builder.
*
* @return
* Function pointer to the implemented callback service.
*/
template <typename BuilderValue>
[[nodiscard]] CONSTEVAL static auto build() {
return run<BuilderValue>;
}
private:
/**
* Runtime implementation of a callback service.
*
* Calls each registered function in an undefined order. The order
* functions are called should not be depended upon and could
* change from one release to the next.
*
* This function will be available from nexus::builder<...> or
* cib::built<...>.
*
* @tparam BuilderValue
* A type that contains a constexpr static value field with the
* fully initialized callback builder.
*
* @param args
* The arguments to be passed to every registered function.
*
* @see cib::nexus
* @see cib::built
*/
template <typename BuilderValue> static void run(ArgTypes... args) {
constexpr auto handler_builder = BuilderValue::value;
[&]<std::size_t... Is>(std::index_sequence<Is...>) {
(handler_builder.funcs[Is](args...), ...);
}(std::make_index_sequence<NumFuncs>{});
}
};
/**
* Extend this to create named callback services.
*
* Types that extend service can be used as unique names with
* cib::exports and cib::extend.
*
* @tparam ArgTypes
* The function arguments that must be passed into the callback
* services implementation. any_t function registered with this
* callback service must also have a compatible signature.
*
* @see cib::exports
* @see cib::extend
*/
template <typename... ArgTypes> struct service {
using builder_t = builder<0, ArgTypes...>;
using interface_t = void (*)(ArgTypes...);
CONSTEVAL static auto uninitialized() -> interface_t {
return [](ArgTypes...) {
stdx::panic<
"Attempting to run callback before it is initialized">();
};
}
};
} // namespace callback

View File

@@ -0,0 +1,45 @@
#pragma once
/*
* Boost Software License - Version 1.0 - August 17th, 2003
*
* Permission is hereby granted, free of charge, to any person or organization
* obtaining a copy of the software and accompanying documentation covered by
* this license (the "Software") to use, reproduce, display, distribute,
* execute, and transmit the Software, and to prepare derivative works of the
* Software, and to permit third-parties to whom the Software is furnished to
* do so, all subject to the following:
*
* The copyright notices in the Software and this entire statement, including
* the above license grant, this restriction and the following disclaimer,
* must be included in all copies of the Software, in whole or in part, and
* all derivative works of the Software, unless such copies or derivative
* works are solely in the form of machine-executable object code generated by
* a source language processor.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
/*
* cib - Compile-time Initialization and Build
* ..~~VERSION~~..
*
* For the documentation and the latest version, see the official github repo:
* https://github.com/intel/compile-time-init-build
*/
#include <cib/builder_meta.hpp>
#include <cib/built.hpp>
#include <cib/callback.hpp>
#include <cib/config.hpp>
#include <cib/func_decl.hpp>
#include <cib/nexus.hpp>
#include <cib/top.hpp>
#include <interrupt/manager.hpp>
#include <log/log.hpp>

View File

@@ -0,0 +1,74 @@
#pragma once
#include <cib/detail/components.hpp>
#include <cib/detail/config_details.hpp>
#include <cib/detail/config_item.hpp>
#include <cib/detail/constexpr_conditional.hpp>
#include <cib/detail/exports.hpp>
#include <cib/detail/extend.hpp>
#include <cib/detail/runtime_conditional.hpp>
#include <stdx/compiler.hpp>
namespace cib {
/**
* Container for project and component configuration declarations.
*
* Each component or project type must contain a static constexpr "config"
* field that contains the cib configuration for that component or project.
* cib::config can be used to compose multiple configuration declarations.
*
* @see cib::components
* @see cib::extend
* @see cib::exports
* @see cib::constexpr_condition
* @see cib::runtime_condition
*/
template <typename... Configs>
[[nodiscard]] CONSTEVAL auto config(Configs const &...configs) {
return detail::config{configs...};
}
/**
* Compose one or more components into a project or larger component.
*
* @tparam Components
* List of components to be added to the configuration.
*/
template <typename... Components>
constexpr static detail::components<Components...> components{};
/**
* Declare a list of services for use in the project.
*
* @tparam Services
*/
template <typename... Services>
constexpr static detail::exports<Services...> exports{};
/**
* Extend a service with new functionality.
*
* @tparam Service
* Type name of the service to extend.
*
* @param args
* Value arguments to be passed to the service's builder add function.
*/
template <typename Service, typename... Args>
[[nodiscard]] CONSTEVAL auto extend(Args const &...args) {
return detail::extend<Service, Args...>{args...};
}
template <stdx::ct_string Name>
constexpr auto constexpr_condition = []<typename P>(P) {
static_assert(std::is_default_constructible_v<P>);
return detail::constexpr_condition<Name, P>{};
};
template <stdx::ct_string Name>
constexpr auto runtime_condition = []<typename P>(P) {
static_assert(std::is_default_constructible_v<P>);
return detail::runtime_condition<Name, P>{};
};
} // namespace cib

View File

@@ -0,0 +1,18 @@
#pragma once
#include <cib/detail/config_item.hpp>
#include <stdx/tuple_algorithms.hpp>
namespace cib::detail {
template <typename... Components>
struct components : public detail::config_item {
[[nodiscard]] constexpr auto extends_tuple() const {
return stdx::tuple_cat(Components::config.extends_tuple()...);
}
[[nodiscard]] constexpr auto exports_tuple() const {
return stdx::tuple_cat(Components::config.exports_tuple()...);
}
};
} // namespace cib::detail

View File

@@ -0,0 +1,36 @@
#pragma once
#include <cib/detail/config_item.hpp>
#include <stdx/compiler.hpp>
#include <stdx/tuple.hpp>
#include <stdx/tuple_algorithms.hpp>
#include <type_traits>
namespace cib::detail {
template <auto Value>
constexpr static auto as_constant_v =
std::integral_constant<std::remove_cvref_t<decltype(Value)>, Value>{};
template <typename... ConfigTs> struct config : public detail::config_item {
stdx::tuple<ConfigTs...> configs_tuple;
CONSTEVAL explicit config(ConfigTs const &...configs)
: configs_tuple{configs...} {}
[[nodiscard]] constexpr auto extends_tuple() const {
return configs_tuple.apply([&](auto const &...configs_pack) {
return stdx::tuple_cat(configs_pack.extends_tuple()...);
});
}
[[nodiscard]] constexpr auto exports_tuple() const {
return configs_tuple.apply([&](auto const &...configs_pack) {
return stdx::tuple_cat(configs_pack.exports_tuple()...);
});
}
};
template <typename... Ts> config(Ts...) -> config<Ts...>;
} // namespace cib::detail

View File

@@ -0,0 +1,15 @@
#pragma once
#include <stdx/tuple.hpp>
namespace cib::detail {
struct config_item {
[[nodiscard]] constexpr static auto extends_tuple() -> stdx::tuple<> {
return {};
}
[[nodiscard]] constexpr static auto exports_tuple() -> stdx::tuple<> {
return {};
}
};
} // namespace cib::detail

View File

@@ -0,0 +1,51 @@
#pragma once
#include <cib/detail/config_details.hpp>
#include <cib/detail/config_item.hpp>
#include <cib/detail/extend.hpp>
#include <stdx/compiler.hpp>
#include <stdx/ct_format.hpp>
#include <stdx/tuple.hpp>
#include <stdx/tuple_algorithms.hpp>
namespace cib::detail {
template <typename Cond, typename... Configs>
struct constexpr_conditional : config_item {
detail::config<Configs...> body;
CONSTEVAL explicit constexpr_conditional(Configs const &...configs)
: body{configs...} {}
[[nodiscard]] constexpr auto extends_tuple() const {
if constexpr (Cond{}) {
return body.extends_tuple();
} else {
return stdx::tuple<>{};
}
}
[[nodiscard]] constexpr auto exports_tuple() const {
if constexpr (Cond{}) {
return body.exports_tuple();
} else {
return stdx::tuple<>{};
}
}
};
template <stdx::ct_string Name, typename... Ps> struct constexpr_condition {
constexpr static auto predicates = stdx::make_tuple(Ps{}...);
constexpr static auto ct_name = Name;
template <typename... Configs>
[[nodiscard]] CONSTEVAL auto operator()(Configs const &...configs) const {
return detail::constexpr_conditional<constexpr_condition<Name, Ps...>,
Configs...>{configs...};
}
explicit constexpr operator bool() const { return (Ps{}() and ...); }
};
} // namespace cib::detail

View File

@@ -0,0 +1,25 @@
#pragma once
#include <cib/detail/config_item.hpp>
#include <cib/detail/extend.hpp>
#include <stdx/tuple.hpp>
namespace cib::detail {
template <typename ServiceT, typename BuilderT> struct service_entry {
using Service = ServiceT;
BuilderT builder;
};
template <typename... Services> struct exports : public detail::config_item {
[[nodiscard]] constexpr auto
extends_tuple() const -> stdx::tuple<extend<Services>...> {
return {extend<Services>{}...};
}
[[nodiscard]] constexpr auto
exports_tuple() const -> stdx::tuple<Services...> {
return {};
}
};
} // namespace cib::detail

View File

@@ -0,0 +1,22 @@
#pragma once
#include <cib/builder_meta.hpp>
#include <cib/detail/config_item.hpp>
#include <stdx/compiler.hpp>
#include <stdx/tuple.hpp>
namespace cib::detail {
template <typename ServiceType, typename... Args>
struct extend : public config_item {
using service_type = ServiceType;
constexpr static auto builder = cib::builder_t<service_type>{};
stdx::tuple<Args...> args_tuple;
CONSTEVAL explicit extend(Args const &...args) : args_tuple{args...} {}
[[nodiscard]] constexpr auto extends_tuple() const -> stdx::tuple<extend> {
return {*this};
}
};
} // namespace cib::detail

View File

@@ -0,0 +1,45 @@
#pragma once
#include <cib/detail/exports.hpp>
#include <stdx/tuple.hpp>
#include <stdx/tuple_algorithms.hpp>
#include <type_traits>
#include <utility>
namespace cib {
template <typename T> using extract_service_tag = typename T::Service;
template <typename T>
using get_service = typename std::remove_cvref_t<T>::service_type;
template <typename T>
using get_service_from_tuple = typename std::remove_cvref_t<
decltype(std::declval<T>()[stdx::index<0>])>::service_type;
template <typename Config>
constexpr static auto initialized_builders = transform<extract_service_tag>(
[](auto extensions) {
using exports_tuple = decltype(Config::config.exports_tuple());
using service = get_service_from_tuple<decltype(extensions)>;
static_assert(stdx::contains_type<exports_tuple, service>);
constexpr auto initial_builder = extensions[stdx::index<0>].builder;
auto built_service = extensions.fold_right(
initial_builder, [](auto extension, auto outer_builder) {
return extension.args_tuple.apply(
[&](auto... args) { return outer_builder.add(args...); });
});
return detail::service_entry<service, decltype(built_service)>{
built_service};
},
stdx::gather_by<get_service>(Config::config.extends_tuple()));
template <typename Config, typename Tag> struct initialized {
constexpr static auto value =
initialized_builders<Config>.get(stdx::tag<Tag>).builder;
};
} // namespace cib

View File

@@ -0,0 +1,94 @@
#pragma once
#include <cib/detail/config_details.hpp>
#include <cib/detail/config_item.hpp>
#include <cib/detail/extend.hpp>
#include <stdx/compiler.hpp>
#include <stdx/concepts.hpp>
#include <stdx/ct_format.hpp>
#include <stdx/tuple.hpp>
#include <stdx/tuple_algorithms.hpp>
namespace cib::detail {
namespace poison {
template <typename... Ts>
constexpr auto make_runtime_conditional(Ts &&...) = delete;
}
template <typename Cond, typename... Configs>
struct runtime_conditional : config_item {
detail::config<Configs...> body;
CONSTEVAL explicit runtime_conditional(Configs const &...configs)
: body{configs...} {}
[[nodiscard]] constexpr auto extends_tuple() const {
return stdx::transform(
[]<typename E>(E e) {
auto args_tuple = stdx::transform(
[]<typename Arg>(Arg) {
using poison::make_runtime_conditional;
return make_runtime_conditional(Cond{}, Arg{});
},
e.args_tuple);
return stdx::apply(
[]<typename... Args>(Args...) {
return extend<typename E::service_type, Args...>{
Args{}...};
},
args_tuple);
},
body.extends_tuple());
}
[[nodiscard]] constexpr auto exports_tuple() const {
return body.exports_tuple();
}
};
template <typename T>
concept runtime_predicate =
std::default_initializable<T> and stdx::predicate<T>;
template <stdx::ct_string Name, runtime_predicate... Ps>
struct runtime_condition {
constexpr static auto predicates = stdx::make_tuple(Ps{}...);
constexpr static auto ct_name = Name;
template <typename... Configs>
[[nodiscard]] CONSTEVAL auto operator()(Configs const &...configs) const {
return detail::runtime_conditional<runtime_condition<Name, Ps...>,
Configs...>{configs...};
}
explicit operator bool() const { return (Ps{}() and ...); }
};
template <stdx::ct_string LhsName, typename... LhsPs, stdx::ct_string RhsName,
typename... RhsPs>
[[nodiscard]] constexpr auto
operator and(runtime_condition<LhsName, LhsPs...> const &lhs,
runtime_condition<RhsName, RhsPs...> const &rhs) {
if constexpr ((sizeof...(LhsPs) + sizeof...(RhsPs)) == 0) {
return runtime_condition<"always">{};
} else if constexpr (sizeof...(LhsPs) == 0) {
return rhs;
} else if constexpr (sizeof...(RhsPs) == 0) {
return lhs;
} else {
constexpr auto name =
stdx::ct_format<"{} and {}">(CX_VALUE(LhsName), CX_VALUE(RhsName));
return runtime_condition<name.str.value, LhsPs..., RhsPs...>{};
}
}
using always_condition_t = runtime_condition<"always">;
constexpr auto always_condition = always_condition_t{};
} // namespace cib::detail

View File

@@ -0,0 +1,12 @@
#pragma once
#include <stdx/ct_string.hpp>
template <stdx::ct_string Name, typename... Args>
extern auto cib_func(Args...) -> void;
namespace cib {
template <stdx::ct_string Name, typename... Args>
constexpr auto func_decl =
[](Args... args) -> void { cib_func<Name>(args...); };
} // namespace cib

View File

@@ -0,0 +1,52 @@
#pragma once
#include <cib/built.hpp>
#include <cib/detail/nexus_details.hpp>
#include <type_traits>
namespace cib {
/**
* Combines all components in a single location so their features can
* extend services.
*
* @tparam Config
* Project configuration class that contains a single constexpr static
* "config" field describing the cib::config
*
* @see cib::config
*/
template <typename Config> struct nexus {
// Workaround unfortunate bug in clang where it can't deduce "auto" sometimes
#define CIB_BUILD_SERVICE \
initialized<Config, Tag>::value.template build<initialized<Config, Tag>>()
template <typename Tag>
constexpr static decltype(CIB_BUILD_SERVICE) service = CIB_BUILD_SERVICE;
#undef CIB_BUILD_SERVICE
static void init() {
auto const service = []<typename T> {
using from_t = std::remove_cvref_t<decltype(nexus::service<T>)>;
using to_t = std::remove_cvref_t<decltype(cib::service<T>)>;
auto &service_impl = nexus::service<T>;
if constexpr (std::is_convertible_v<from_t, to_t>) {
cib::service<T> = service_impl;
} else {
if constexpr (std::is_pointer_v<from_t>) {
cib::service<T> = service_impl;
} else {
cib::service<T> = &service_impl;
}
}
};
initialized_builders<Config>.apply([&]<typename... Ts>(Ts const &...) {
(service.template
operator()<std::remove_cvref_t<typename Ts::Service>>(),
...);
});
}
};
} // namespace cib

View File

@@ -0,0 +1,72 @@
#pragma once
#include <cib/config.hpp>
#include <cib/nexus.hpp>
#include <flow/flow.hpp>
namespace cib {
/**
* Executed immediately after the C++ runtime is stable. This should be
* used to initialize essential services like logging and potentially
* configure the host system the project is running on.
*/
class EarlyRuntimeInit : public flow::service<> {};
/**
* Executed once after essential services like logging are initialized.
* This can be used for general component runtime initialization.
*/
class RuntimeInit : public flow::service<> {};
/**
* Executed after all runtime initialization is completed. This is where
* the project can start doing its job including enabling interrupts and/or
* starting threads if applicable and be ready to start accepting and
* processing external events.
*/
class RuntimeStart : public flow::service<> {};
/**
* Executed repeated in an infinite loop after initialization and
* RuntimeStart flows have completed.
*/
class MainLoop : public flow::service<> {};
/**
* The top object for cib framework. Call 'main' to execute the project.
*/
template <typename ProjectConfig> class top {
private:
struct component {
constexpr static auto config = cib::config(
cib::exports<EarlyRuntimeInit, RuntimeInit, RuntimeStart, MainLoop>,
cib::components<ProjectConfig>);
};
constexpr static cib::nexus<component> my_nexus{};
public:
/**
* Main entry point to cib top.
*/
[[noreturn]] inline void main() {
my_nexus.init();
flow::run<EarlyRuntimeInit>();
CIB_INFO("cib::top::init() - RuntimeInit");
flow::run<RuntimeInit>();
CIB_INFO("cib::top::init() - RuntimeStart");
flow::run<RuntimeStart>();
while (true) {
flow::run<MainLoop>();
}
}
template <typename ServiceMeta>
constexpr static auto get_service() -> auto & {
return my_nexus.template service<ServiceMeta>;
}
};
} // namespace cib

View File

@@ -0,0 +1,196 @@
#pragma once
#include <conc/concepts.hpp>
#include <atomic>
#include <memory>
#include <type_traits>
#if __cplusplus >= 202002L
#define CPP20(...) __VA_ARGS__
#else
#define CPP20(...)
#endif
namespace atomic {
namespace detail {
struct standard_policy {
static_assert(static_cast<int>(std::memory_order_relaxed) ==
__ATOMIC_RELAXED);
static_assert(static_cast<int>(std::memory_order_acquire) ==
__ATOMIC_ACQUIRE);
static_assert(static_cast<int>(std::memory_order_release) ==
__ATOMIC_RELEASE);
static_assert(static_cast<int>(std::memory_order_seq_cst) ==
__ATOMIC_SEQ_CST);
static_assert(static_cast<int>(std::memory_order_acq_rel) ==
__ATOMIC_ACQ_REL);
static_assert(static_cast<int>(std::memory_order_consume) ==
__ATOMIC_CONSUME);
template <typename T>
static auto load(T const &t,
std::memory_order mo = std::memory_order_seq_cst) -> T {
T ret{};
__atomic_load(std::addressof(t), std::addressof(ret),
static_cast<int>(mo));
return ret;
}
template <typename T>
static auto
store(T &t, T &value,
std::memory_order mo = std::memory_order_seq_cst) -> void {
__atomic_store(std::addressof(t), std::addressof(value),
static_cast<int>(mo));
}
template <typename T>
static auto
exchange(T &t, T &value,
std::memory_order mo = std::memory_order_seq_cst) -> T {
T ret{};
__atomic_exchange(std::addressof(t), std::addressof(value),
std::addressof(ret), static_cast<int>(mo));
return ret;
}
template <typename T>
static auto
fetch_add(T &t, T value,
std::memory_order mo = std::memory_order_seq_cst) -> T {
return __atomic_fetch_add(std::addressof(t), value,
static_cast<int>(mo));
}
template <typename T>
static auto
fetch_sub(T &t, T value,
std::memory_order mo = std::memory_order_seq_cst) -> T {
return __atomic_fetch_sub(std::addressof(t), value,
static_cast<int>(mo));
}
template <typename T>
static auto
fetch_and(T &t, T value,
std::memory_order mo = std::memory_order_seq_cst) -> T {
return __atomic_fetch_and(std::addressof(t), value,
static_cast<int>(mo));
}
template <typename T>
static auto
fetch_or(T &t, T value,
std::memory_order mo = std::memory_order_seq_cst) -> T {
return __atomic_fetch_or(std::addressof(t), value,
static_cast<int>(mo));
}
template <typename T>
static auto
fetch_xor(T &t, T value,
std::memory_order mo = std::memory_order_seq_cst) -> T {
return __atomic_fetch_xor(std::addressof(t), value,
static_cast<int>(mo));
}
};
} // namespace detail
template <typename...> inline auto injected_policy = detail::standard_policy{};
template <typename... DummyArgs, typename T>
CPP20(requires(sizeof...(DummyArgs) == 0))
[[nodiscard]] auto load(T const &t,
std::memory_order mo = std::memory_order_seq_cst) -> T {
CPP20(load_store_policy)
auto &p = injected_policy<DummyArgs...>;
return p.load(t, mo);
}
template <typename... DummyArgs, typename T, typename U,
typename = std::enable_if_t<std::is_convertible_v<U, T>>>
CPP20(requires(sizeof...(DummyArgs) == 0))
auto store(T &t, U value,
std::memory_order mo = std::memory_order_seq_cst) -> void {
CPP20(load_store_policy)
auto &p = injected_policy<DummyArgs...>;
auto v = static_cast<T>(value);
p.store(t, v, mo);
}
template <typename... DummyArgs, typename T, typename U,
typename = std::enable_if_t<std::is_convertible_v<U, T>>>
CPP20(requires(sizeof...(DummyArgs) == 0))
[[nodiscard]] auto exchange(
T &t, U value, std::memory_order mo = std::memory_order_seq_cst) -> T {
CPP20(exchange_policy)
auto &p = injected_policy<DummyArgs...>;
auto v = static_cast<T>(value);
return p.exchange(t, v, mo);
}
template <typename... DummyArgs, typename T, typename U,
typename = std::enable_if_t<std::is_convertible_v<U, T>>>
CPP20(requires(sizeof...(DummyArgs) == 0))
auto fetch_add(T &t, U value,
std::memory_order mo = std::memory_order_seq_cst) -> T {
CPP20(add_sub_policy)
auto &p = injected_policy<DummyArgs...>;
return p.fetch_add(t, static_cast<T>(value), mo);
}
template <typename... DummyArgs, typename T, typename U,
typename = std::enable_if_t<std::is_convertible_v<U, T>>>
CPP20(requires(sizeof...(DummyArgs) == 0))
auto fetch_sub(T &t, U value,
std::memory_order mo = std::memory_order_seq_cst) -> T {
CPP20(add_sub_policy)
auto &p = injected_policy<DummyArgs...>;
return p.fetch_sub(t, static_cast<T>(value), mo);
}
template <typename... DummyArgs, typename T, typename U,
typename = std::enable_if_t<std::is_convertible_v<U, T>>>
CPP20(requires(sizeof...(DummyArgs) == 0))
auto fetch_and(T &t, U value,
std::memory_order mo = std::memory_order_seq_cst) -> T {
CPP20(bitwise_policy)
auto &p = injected_policy<DummyArgs...>;
return p.fetch_and(t, static_cast<T>(value), mo);
}
template <typename... DummyArgs, typename T, typename U,
typename = std::enable_if_t<std::is_convertible_v<U, T>>>
CPP20(requires(sizeof...(DummyArgs) == 0))
auto fetch_or(T &t, U value,
std::memory_order mo = std::memory_order_seq_cst) -> T {
CPP20(bitwise_policy)
auto &p = injected_policy<DummyArgs...>;
return p.fetch_or(t, static_cast<T>(value), mo);
}
template <typename... DummyArgs, typename T, typename U,
typename = std::enable_if_t<std::is_convertible_v<U, T>>>
CPP20(requires(sizeof...(DummyArgs) == 0))
auto fetch_xor(T &t, U value,
std::memory_order mo = std::memory_order_seq_cst) -> T {
CPP20(bitwise_policy)
auto &p = injected_policy<DummyArgs...>;
return p.fetch_xor(t, static_cast<T>(value), mo);
}
template <typename T> struct atomic_type {
using type = T;
};
template <typename T> using atomic_type_t = typename atomic_type<T>::type;
template <typename T>
constexpr inline auto alignment_of = alignof(std::atomic<atomic_type_t<T>>);
} // namespace atomic
#undef CPP20
#ifdef ATOMIC_CFG
#include ATOMIC_CFG
#endif

View File

@@ -0,0 +1,56 @@
#pragma once
#if __cplusplus >= 202002L
#include <atomic>
#include <concepts>
namespace conc {
template <typename T>
concept policy = requires(auto (*f)()->int &&, auto (*pred)()->bool) {
{ T::call_in_critical_section(f) } -> std::same_as<int &&>;
{ T::call_in_critical_section(f, pred) } -> std::same_as<int &&>;
};
} // namespace conc
namespace atomic {
template <typename T>
concept load_store_policy = requires(int &a, int value, std::memory_order mo) {
{ T::load(a) } -> std::same_as<int>;
{ T::load(a, mo) } -> std::same_as<int>;
{ T::store(a, value) } -> std::same_as<void>;
{ T::store(a, value, mo) } -> std::same_as<void>;
};
template <typename T>
concept exchange_policy =
load_store_policy<T> and requires(int &a, int value, std::memory_order mo) {
{ T::exchange(a, value) } -> std::same_as<int>;
{ T::exchange(a, value, mo) } -> std::same_as<int>;
};
template <typename T>
concept add_sub_policy =
load_store_policy<T> and requires(int &a, int value, std::memory_order mo) {
{ T::fetch_add(a, value) } -> std::same_as<int>;
{ T::fetch_add(a, value, mo) } -> std::same_as<int>;
{ T::fetch_sub(a, value) } -> std::same_as<int>;
{ T::fetch_sub(a, value, mo) } -> std::same_as<int>;
};
template <typename T>
concept bitwise_policy =
load_store_policy<T> and requires(int &a, int value, std::memory_order mo) {
{ T::fetch_and(a, value) } -> std::same_as<int>;
{ T::fetch_and(a, value, mo) } -> std::same_as<int>;
{ T::fetch_or(a, value) } -> std::same_as<int>;
{ T::fetch_or(a, value, mo) } -> std::same_as<int>;
{ T::fetch_xor(a, value) } -> std::same_as<int>;
{ T::fetch_xor(a, value, mo) } -> std::same_as<int>;
};
template <typename T>
concept policy = exchange_policy<T> and add_sub_policy<T> and bitwise_policy<T>;
} // namespace atomic
#endif

View File

@@ -0,0 +1,67 @@
#pragma once
#ifdef SIMULATE_FREESTANDING
#define HAS_MUTEX 0
#else
#define HAS_MUTEX __has_include(<mutex>)
#endif
#include <conc/concepts.hpp>
#if HAS_MUTEX
#include <mutex>
#endif
#include <concepts>
#include <utility>
namespace conc {
namespace detail {
template <typename...> constexpr auto always_false_v = false;
#if HAS_MUTEX
template <typename Mutex = std::mutex> class standard_policy {
template <typename> static inline Mutex m{};
public:
template <typename Uniq = void, std::invocable F, std::predicate... Pred>
requires(sizeof...(Pred) < 2)
static auto call_in_critical_section(F &&f, Pred &&...pred)
-> decltype(std::forward<F>(f)()) {
while (true) {
[[maybe_unused]] std::lock_guard l{m<Uniq>};
if ((... and pred())) {
return std::forward<F>(f)();
}
}
}
};
#else
template <typename = void> struct standard_policy {
template <typename = void, std::invocable F, std::predicate... Pred>
requires(sizeof...(Pred) < 2)
static auto call_in_critical_section(F &&f, Pred &&...)
-> decltype(std::forward<F>(f)()) {
static_assert(always_false_v<F, Pred...>,
"No standard concurrency policy defined: inject a policy "
"by specializing conc::injected_policy<>");
return std::forward<F>(f)();
}
};
#endif
} // namespace detail
template <typename...> inline auto injected_policy = detail::standard_policy{};
template <typename Uniq = decltype([] {}), typename... DummyArgs,
std::invocable F, std::predicate... Pred>
requires(sizeof...(DummyArgs) == 0 and sizeof...(Pred) < 2)
auto call_in_critical_section(F &&f, Pred &&...pred)
-> decltype(std::forward<F>(f)()) {
policy auto &p = injected_policy<DummyArgs...>;
return p.template call_in_critical_section<Uniq>(
std::forward<F>(f), std::forward<Pred>(pred)...);
}
} // namespace conc
#undef HAS_MUTEX

Some files were not shown because too many files have changed in this diff Show More