diff --git a/CMakeLists.txt b/CMakeLists.txt index 319f373..27854a8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,6 +47,7 @@ endmacro(add_test_executable) add_test_executable(always) add_test_executable(args) +add_test_executable(builder) add_test_executable(conditional) add_test_executable(compose) add_test_executable(fix) diff --git a/fit/builder.h b/fit/builder.h new file mode 100644 index 0000000..4cd223c --- /dev/null +++ b/fit/builder.h @@ -0,0 +1,283 @@ +/*============================================================================= + Copyright (c) 2014 Paul Fultz II + builder.h + 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) +==============================================================================*/ + +#ifndef FIT_GUARD_BUILDER_H +#define FIT_GUARD_BUILDER_H + +#include +#include +#include +#include +#include +#include + +#define FIT_PP_TRUE(...) 1 +#define FIT_PP_FALSE(...) 0 + +// +// FIT_PP_IS_EMPTY will expands to 1 if the parameter is empty, otherwise +// it expands to 0. This will work even if the parameter given is a set +// of parenthesis. +// +#define FIT_PP_IS_EMPTY(x) BOOST_PP_CAT(FIT_PP_DETAIL_IS_EMPTY_, FIT_PP_IS_PAREN(x))(x) +#define FIT_PP_DETAIL_IS_EMPTY_0(x) BOOST_PP_IS_EMPTY(x) +#define FIT_PP_DETAIL_IS_EMPTY_1(x) 0 + +// +// FIT_PP_HEAD retrieves the first element of a sequence. +// Example: +// +// FIT_PP_HEAD((1)(2)(3)) // Expands to (1) +// +#define FIT_PP_HEAD(x) FIT_PP_PICK_HEAD(FIT_PP_MARK x) +#define FIT_PP_MARK(...) (__VA_ARGS__), +#define FIT_PP_PICK_HEAD(...) FIT_PP_PICK_HEAD_I(__VA_ARGS__,) +#define FIT_PP_PICK_HEAD_I(x, ...) x + + +// +// FIT_PP_TAIL retrieves the tail of a sequence. +// Example: +// +// FIT_PP_TAIL((1)(2)(3)) // Expands to (2)(3) +// +#define FIT_PP_TAIL(x) FIT_PP_EAT x + +// +// FIT_PP_ARGS_TO_SEQ converts args to a seq +// +#define FIT_PP_ARGS_TO_SEQ(...) FIT_PP_DETAIL_ARGS_TO_SEQ(FIT_PP_NARGS(__VA_ARGS__), (__VA_ARGS__)) +#define FIT_PP_DETAIL_ARGS_TO_SEQ(size, tuple) BOOST_PP_TUPLE_TO_SEQ(size, tuple) + +#define FIT_PP_SEQ_IS_SINGLE(x) FIT_PP_IS_1(BOOST_PP_SEQ_SIZE(x)) + +#define FIT_PP_TYPEOF(x) FIT_PP_DETAIL_TYPEOF(FIT_PP_DETAIL_TYPEOF_PROBE x,) +#define FIT_PP_DETAIL_TYPEOF(...) FIT_PP_DETAIL_TYPEOF_HEAD(__VA_ARGS__) +#define FIT_PP_DETAIL_TYPEOF_HEAD(x, ...) FIT_PP_REM x +#define FIT_PP_DETAIL_TYPEOF_PROBE(...) (__VA_ARGS__), + +#define FIT_PP_STRIP(x) FIT_PP_EAT x + +#define FIT_PP_PAIR(x) FIT_PP_REM x + +// +// FIT_PP_STRING_TOKEN +// +#define FIT_PP_STRING_TOKEN(x) BOOST_PP_IIF(FIT_PP_IS_PAREN(x), FIT_PP_STRING_TOKEN_PAREN, FIT_PP_STRING_TOKEN_KEYWORD)(x) +#define FIT_PP_STRING_TOKEN_KEYWORD(x) FIT_PP_STRING_TOKEN_KEYWORD_CHECK(BOOST_PP_CAT(FIT_PP_STRING_, x), x) +#define FIT_PP_STRING_TOKEN_KEYWORD_CHECK(tokened, raw) BOOST_PP_IIF(FIT_PP_IS_PAREN(tokened), tokened, (raw)) +#define FIT_PP_STRING_TOKEN_PAREN(x) (FIT_PP_HEAD(x)) FIT_PP_TAIL(x) + +// +// FIT_PP_STRING_TO_SEQ converts a string into a preprocessor sequence +// +#define FIT_PP_STRING_TO_SEQ(x) FIT_PP_STRING_TO_SEQ_WHILE_M \ +( \ + BOOST_PP_WHILE(FIT_PP_STRING_TO_SEQ_WHILE_P, FIT_PP_STRING_TO_SEQ_WHILE_O, (,x)) \ +) + +#define FIT_PP_STRING_TO_SEQ_WHILE_P(r, state) FIT_PP_STRING_TO_SEQ_P state +#define FIT_PP_STRING_TO_SEQ_WHILE_O(r, state) FIT_PP_STRING_TO_SEQ_O state +#define FIT_PP_STRING_TO_SEQ_WHILE_M(state) FIT_PP_STRING_TO_SEQ_M state + +#define FIT_PP_STRING_TO_SEQ_P(prev, tail) BOOST_PP_NOT(FIT_PP_IS_EMPTY(tail)) +#define FIT_PP_STRING_TO_SEQ_O(prev, tail) \ + FIT_PP_STRING_TO_SEQ_REPLACE(prev, FIT_PP_STRING_TOKEN(tail)) + +#define FIT_PP_STRING_TO_SEQ_REPLACE(prev, tail) \ + (prev FIT_PP_HEAD(tail), FIT_PP_TAIL(tail)) + +#define FIT_PP_STRING_TO_SEQ_M(prev, tail) prev + +// +// FIT_PP_SEQ_TO_STRING outputs the sequence +// +// TODO: Use sequence iteration +#define FIT_PP_SEQ_TO_STRING(seq) BOOST_PP_SEQ_FOR_EACH(FIT_PP_SEQ_TO_STRING_EACH, ~, seq) +#define FIT_PP_SEQ_TO_STRING_EACH(r, data, x) x + +// +// FIT_PP_SEQ_SPLIT +// +#define FIT_PP_SEQ_SPLIT(seq, pred, data) FIT_DETAIL_PP_SEQ_SPLIT_FOLD_LEFT_M(BOOST_PP_SEQ_FOLD_LEFT(FIT_DETAIL_PP_SEQ_SPLIT_FOLD_LEFT_O, (pred, data,,), seq)) +#define FIT_DETAIL_PP_SEQ_SPLIT_FOLD_LEFT_O(s, state, x) FIT_DETAIL_PP_SEQ_SPLIT_FOLD_LEFT_INVOKE((s, x, FIT_PP_REM state)) +#define FIT_DETAIL_PP_SEQ_SPLIT_FOLD_LEFT_INVOKE(x) FIT_DETAIL_PP_SEQ_SPLIT_OP x +#define FIT_DETAIL_PP_SEQ_SPLIT_OP(s, x, pred, data, seq, elem) \ + BOOST_PP_IF(pred(s, data, x), FIT_DETAIL_PP_SEQ_SPLIT_OP_TRUE, FIT_DETAIL_PP_SEQ_SPLIT_OP_FALSE)(x, pred, data, seq, elem) +#define FIT_DETAIL_PP_SEQ_SPLIT_OP_TRUE(x, pred, data, seq, elem) BOOST_PP_IIF(FIT_PP_IS_PAREN(elem), \ + (pred, data, seq(elem),),\ + (pred, data, seq,)) +#define FIT_DETAIL_PP_SEQ_SPLIT_OP_FALSE(x, pred, data, seq, elem) (pred, data, seq, elem (x)) +#define FIT_DETAIL_PP_SEQ_SPLIT_FOLD_LEFT_M(state) FIT_DETAIL_PP_SEQ_SPLIT_M state +#define FIT_DETAIL_PP_SEQ_SPLIT_M(pred, data, seq, elem) seq BOOST_PP_IIF(FIT_PP_IS_PAREN(elem), (elem),) + + +// +// FIT_PP_EQUAL +// +#define FIT_PP_IS_COMPARABLE(x) BOOST_PP_IIF(FIT_PP_IS_PAREN(x), FIT_PP_FALSE, FIT_PP_PRIMITIVE_IS_COMPARABLE)(x) +#define FIT_PP_PRIMITIVE_IS_COMPARABLE(x) FIT_PP_IS_PAREN( FIT_PP_COMPARE_ ## x (()) ) +#define FIT_PP_PRIMITIVE_COMPARE(x, y) FIT_PP_IS_PAREN \ +( \ +FIT_PP_COMPARE_ ## x ( FIT_PP_COMPARE_ ## y) ((unused)) \ +) +#define FIT_PP_NOT_EQUAL(x, y) \ +BOOST_PP_IIF(BOOST_PP_BITAND( FIT_PP_IS_COMPARABLE(x), FIT_PP_IS_COMPARABLE(y) ), \ +FIT_PP_PRIMITIVE_COMPARE, \ +FIT_PP_TRUE \ +)(x, y) +#define FIT_PP_EQUAL(x, y) BOOST_PP_COMPL(FIT_PP_NOT_EQUAL(x, y)) + + + +#ifndef FIT_PP_STRING_if +#define FIT_PP_STRING_if (if) +#endif +#ifndef FIT_PP_STRING_else +#define FIT_PP_STRING_else (else) +#endif +#ifndef FIT_PP_COMPARE_else +#define FIT_PP_COMPARE_else(x) x +#endif + +#define FIT_FUNCTION_PARAM(x) BOOST_PP_CAT(FIT_FUNCTION_PARAM_, x) +#define FIT_FUNCTION_PARAM_const (const) +#define FIT_FUNCTION_PARAM_auto (()) + +#define FIT_FUNCTION_PARAM_IF_PARAM(x, t, f, data) FIT_DETAIL_FUNCTION_IF_PARAM(FIT_FUNCTION_PARAM(x), x, t, f, data) +#define FIT_DETAIL_FUNCTION_IF_PARAM(x, y, t, f, data) BOOST_PP_IIF(FIT_PP_IS_PAREN(x), t, f)(x, y, data) + +#define FIT_FUNCTION_PARAM_REPLACE_ID() FIT_FUNCTION_PARAM_REPLACE + +#define FIT_FUNCTION_PARAM_REPLACE(x, T) FIT_FUNCTION_PARAM_IF_PARAM(x, FIT_DETAIL_FUNCTION_PARAM_REPLACE_TRUE, FIT_DETAIL_FUNCTION_PARAM_REPLACE_FALSE, T) +#define FIT_DETAIL_FUNCTION_PARAM_REPLACE_TRUE(x, y, T) FIT_DETAIL_FUNCTION_PARAM_REPLACE_TRUE_I(FIT_PP_TYPEOF(x), FIT_PP_STRIP(x), T) +#define FIT_DETAIL_FUNCTION_PARAM_REPLACE_TRUE_I(head, tail, T) \ + BOOST_PP_IIF(FIT_PP_IS_PAREN(head), FIT_DETAIL_FUNCTION_PARAM_REPLACE_END, FIT_DETAIL_FUNCTION_PARAM_REPLACE_CONT)(head, tail, T) +#define FIT_DETAIL_FUNCTION_PARAM_REPLACE_END(head, tail, T) T tail +#define FIT_DETAIL_FUNCTION_PARAM_REPLACE_CONT(head, tail, T) head FIT_PP_DEFER(FIT_FUNCTION_PARAM_REPLACE_ID)()(tail, T) +#define FIT_DETAIL_FUNCTION_PARAM_REPLACE_FALSE(x, y, T) y + +#define FIT_FUNCTION_PARAM_TEMPLATE_ID() FIT_FUNCTION_PARAM_TEMPLATE + +#define FIT_FUNCTION_PARAM_TEMPLATE(x, T) FIT_FUNCTION_PARAM_IF_PARAM(x, FIT_DETAIL_FUNCTION_PARAM_TEMPLATE_TRUE, FIT_DETAIL_FUNCTION_PARAM_TEMPLATE_FALSE, T) +#define FIT_DETAIL_FUNCTION_PARAM_TEMPLATE_TRUE(x, y, T) FIT_DETAIL_FUNCTION_PARAM_TEMPLATE_TRUE_I(FIT_PP_TYPEOF(x), FIT_PP_STRIP(x), T) +#define FIT_DETAIL_FUNCTION_PARAM_TEMPLATE_TRUE_I(head, tail, T) \ + BOOST_PP_IIF(FIT_PP_IS_PAREN(head), FIT_DETAIL_FUNCTION_PARAM_TEMPLATE_END, FIT_DETAIL_FUNCTION_PARAM_TEMPLATE_CONT)(head, tail, T) +#define FIT_DETAIL_FUNCTION_PARAM_TEMPLATE_END(head, tail, T) (class T) +#define FIT_DETAIL_FUNCTION_PARAM_TEMPLATE_CONT(head, tail, T) FIT_PP_DEFER(FIT_FUNCTION_PARAM_TEMPLATE_ID)()(tail, T) +#define FIT_DETAIL_FUNCTION_PARAM_TEMPLATE_FALSE(x, y, T) + +#define FIT_PP_SEQ_FOR_EACH_ID() BOOST_PP_SEQ_FOR_EACH_I +#define FIT_PP_SEQ_FOR_EACH_I_R_ID() BOOST_PP_SEQ_FOR_EACH_I_R + +#define FIT_FUNCTION_PARAM_TEMPLATE_ARGS(r, seq, T) BOOST_PP_SEQ_FOR_EACH_I_R(r, FIT_FUNCTION_PARAM_TEMPLATE_ARGS_EACH, T, seq) +#define FIT_FUNCTION_PARAM_TEMPLATE_ARGS_EACH(r, T, i, elem) FIT_FUNCTION_PARAM_TEMPLATE(elem, T ## i) + +#define FIT_FUNCTION_PARAM_REPLACE_AUTO(r, seq, T) BOOST_PP_SEQ_FOR_EACH_I_R(r, FIT_FUNCTION_PARAM_REPLACE_AUTO_EACH, T, seq) +#define FIT_FUNCTION_PARAM_REPLACE_AUTO_EACH(r, T, i, elem) (FIT_FUNCTION_PARAM_REPLACE(elem, T ## i)) + + +#define FIT_PARAM_REQUIRES(reqs) typename std::enable_if<(decltype reqs ()), int>::type = 0 +#define FIT_DETAIL_FUNCTION_CLASS_K_REQ(reqs) , FIT_PARAM_REQUIRES(reqs) +#define FIT_DETAIL_FUNCTION_CLASS_K(name, n, t_params, f_params, reqs, body) \ +struct name \ +{ \ + template \ + decltype(auto) \ + operator()(BOOST_PP_SEQ_ENUM(f_params) \ + BOOST_PP_IIF(FIT_PP_IS_PAREN(reqs), FIT_DETAIL_FUNCTION_CLASS_K_REQ, FIT_PP_EAT)(reqs) \ + ) const \ + { return body; } \ +}; + +// TODO: Add support for bodies without double parenthesis, so you can write: +// FIT_FUNCTIONS_CLASS((foo)(x, y) x + y) +#define FIT_DETAIL_FUNCTION_CLASS_GEN(name, n, t_params, f_params, body) \ +BOOST_PP_CAT(FIT_DETAIL_FUNCTION_CLASS_GEN_, BOOST_PP_SEQ_SIZE(body))\ +(name, n, t_params, f_params, body) +#define FIT_DETAIL_FUNCTION_CLASS_GEN_1(name, n, t_params, f_params, body) \ +FIT_DETAIL_FUNCTION_CLASS_K(name, n, t_params, f_params,, BOOST_PP_SEQ_HEAD(body)) +#define FIT_DETAIL_FUNCTION_CLASS_GEN_3(name, n, t_params, f_params, body) \ +FIT_DETAIL_FUNCTION_CLASS_K(name, n, t_params, f_params, BOOST_PP_SEQ_ELEM(1, body), BOOST_PP_SEQ_ELEM(2, body)) + +// +// Conditional adaptor +// +#define FIT_DETAIL_FUNCTION_CLASS_CONDITIONAL_EACH(r, data, i, x) FIT_DETAIL_FUNCTION_CLASS_INVOKE((i, FIT_PP_REM data, x)) +#define FIT_DETAIL_FUNCTION_CLASS_INVOKE(x) FIT_DETAIL_FUNCTION_CLASS_OP x +#define FIT_DETAIL_FUNCTION_CLASS_OP(i, name, n, t_params, f_params, body) \ +FIT_DETAIL_FUNCTION_CLASS_GEN(FIT_DETAIL_FUNCTION_CLASS_CONDITIONAL_NAME(i, name), n, t_params, f_params, body) + +#define FIT_DETAIL_FUNCTION_CLASS_CONDITIONAL_NAME(i, name) BOOST_PP_CAT(fit_888_, BOOST_PP_CAT(i, name)) +#define FIT_DETAIL_FUNCTION_CLASS_CONDITIONAL_NAMES(n, name) BOOST_PP_ENUM(n, FIT_DETAIL_FUNCTION_CLASS_CONDITIONAL_NAMES_EACH, name) +#define FIT_DETAIL_FUNCTION_CLASS_CONDITIONAL_NAMES_EACH(z, i, name) FIT_DETAIL_FUNCTION_CLASS_CONDITIONAL_NAME(i, name) + +#define FIT_DETAIL_FUNCTION_CLASS_CONDITIONAL_PARSE_ARGS(r, self, params) \ + (class Fit_8Self)FIT_FUNCTION_PARAM_TEMPLATE_ARGS(r, params, Fit_8T), (Fit_8Self self)FIT_FUNCTION_PARAM_REPLACE_AUTO(r, params, Fit_8T) + +#define FIT_DETAIL_FUNCTION_CLASS_CONDITIONAL_ALL(r, self, name, n, params, bodies) \ +FIT_PP_DEFER(FIT_PP_SEQ_FOR_EACH_I_R_ID)()(r, FIT_DETAIL_FUNCTION_CLASS_CONDITIONAL_EACH, \ + (name, n, FIT_DETAIL_FUNCTION_CLASS_CONDITIONAL_PARSE_ARGS(r, self, params)), \ + bodies) \ + typedef fit::fix_adaptor > name; + +#define FIT_DETAIL_FUNCTION_CLASS_CONDITIONAL_SINGLE_INVOKE(x) FIT_DETAIL_FUNCTION_CLASS_GEN x + +#define FIT_DETAIL_FUNCTION_CLASS_CONDITIONAL_SINGLE(r, self, name, n, params, body) \ + FIT_DETAIL_FUNCTION_CLASS_CONDITIONAL_SINGLE_INVOKE((FIT_DETAIL_FUNCTION_CLASS_CONDITIONAL_NAME(0, name), n, FIT_DETAIL_FUNCTION_CLASS_CONDITIONAL_PARSE_ARGS(r, self, params), FIT_PP_REM body)) \ + typedef fit::fix_adaptor name; + +#define FIT_DETAIL_FUNCTION_CLASS_CONDITIONAL(r, self, name, params, bodies) BOOST_PP_IIF(FIT_PP_SEQ_IS_SINGLE(bodies), \ + FIT_DETAIL_FUNCTION_CLASS_CONDITIONAL_SINGLE, \ + FIT_DETAIL_FUNCTION_CLASS_CONDITIONAL_ALL)\ + (r, self, name, FIT_PP_NARGS params, FIT_PP_ARGS_TO_SEQ params, bodies) + +#define FIT_DETAIL_FUNCTION_CLASS_CONDITIONAL_P(s, data, x) FIT_PP_EQUAL(x, else) +#define FIT_DETAIL_FUNCTION_CLASS_CONDITIONAL_SPLIT(seq) FIT_PP_SEQ_SPLIT(seq, FIT_DETAIL_FUNCTION_CLASS_CONDITIONAL_P, data) + + +#define FIT_DETAIL_FUNCTION_CLASS_NAME(seq) FIT_DETAIL_FUNCTION_CLASS_NAME_I(BOOST_PP_SEQ_ELEM(0, seq)) +#define FIT_DETAIL_FUNCTION_CLASS_NAME_I(x) FIT_PP_REM x + +// #define FIT_DETAIL_FUNCTION_CLASS_TRANSFORM_TAIL(self, name, seq) TRANSFORM_TAIL(self, name, seq) +#define FIT_DETAIL_FUNCTION_CLASS_TRANSFORM_TAIL(self, name, seq) \ +FIT_DETAIL_FUNCTION_CLASS_CONDITIONAL(1, self, name, BOOST_PP_SEQ_HEAD(seq), FIT_DETAIL_FUNCTION_CLASS_CONDITIONAL_SPLIT(BOOST_PP_SEQ_TAIL(seq))) + +#define FIT_DETAIL_FUNCTION_CLASS_TRANSFORM_WITH_NAME(name, seq) FIT_DETAIL_FUNCTION_CLASS_TRANSFORM_TAIL(FIT_DETAIL_FUNCTION_CLASS_NAME(seq), name, BOOST_PP_SEQ_TAIL(seq)) +#define FIT_DETAIL_FUNCTION_CLASS_TRANSFORM_WITHOUT_NAME(seq) FIT_DETAIL_FUNCTION_CLASS_TRANSFORM_TAIL(FIT_DETAIL_FUNCTION_CLASS_NAME(seq), FIT_DETAIL_FUNCTION_CLASS_NAME(seq), BOOST_PP_SEQ_TAIL(seq)) +// #define FIT_DETAIL_FUNCTION_CLASS_TRANSFORM_WITHOUT_NAME(seq) TRANSFORM_WITHOUT_NAME(seq) + + +// Apply additional scans +#define FIT_DETAIL_FUNCTION_CLASS_XX(...) __VA_ARGS__ +#define FIT_DETAIL_FUNCTION_CLASS_X(...) FIT_DETAIL_FUNCTION_CLASS_XX(FIT_DETAIL_FUNCTION_CLASS_XX(__VA_ARGS__)) + +// class +#define FIT_FUNCTION_CLASS(x) FIT_DETAIL_FUNCTION_CLASS_X(FIT_DETAIL_FUNCTION_CLASS_TRANSFORM_WITHOUT_NAME(FIT_PP_STRING_TO_SEQ(x))) +#define FIT_FUNCTION_CLASS_NAME(name, x) FIT_DETAIL_FUNCTION_CLASS_X(FIT_DETAIL_FUNCTION_CLASS_TRANSFORM_WITH_NAME(name, FIT_PP_STRING_TO_SEQ(x))) + +// function object +#define FIT_DETAIL_FUNCTION_OBJECT(name, x) FIT_FUNCTION_CLASS_NAME(BOOST_PP_CAT(fit_class_, name), x) const fit::static_ name = {}; +#define FIT_FUNCTION_OBJECT(x) FIT_DETAIL_FUNCTION_OBJECT(BOOST_PP_SEQ_HEAD(x), x) + +// pipe +#define FIT_DETAIL_FUNCTION_PIPE_OBJECT(name, x) FIT_FUNCTION_CLASS_NAME(BOOST_PP_CAT(fit_class_, name), x) fit::static_ > name = {}; +#define FIT_FUNCTION_PIPE_OBJECT(x) FIT_DETAIL_FUNCTION_PIPE_OBJECT(BOOST_PP_SEQ_HEAD(x), x) + +#define FIT_FUNCTION_KEYWORD_class (FIT_FUNCTION_CLASS) + +#define FIT_FUNCTION_KEYWORD_pipe (FIT_FUNCTION_PIPE_OBJECT) + +// Register with ZLANG +#define ZLANG_fit_function (FIT_FUNCTION) + +#define FIT_FUNCTION_INVOKE(m, args) m args +#define FIT_FUNCTION_II(x) FIT_FUNCTION_INVOKE(BOOST_PP_SEQ_HEAD(x), (BOOST_PP_SEQ_TAIL(x))) +#define FIT_FUNCTION_I(x) FIT_FUNCTION_II(BOOST_PP_CAT(FIT_FUNCTION_KEYWORD_, x)) +#define FIT_FUNCTION(x) BOOST_PP_IIF(FIT_PP_IS_PAREN(x), FIT_FUNCTION_OBJECT, FIT_FUNCTION_I)(x) + +#endif \ No newline at end of file diff --git a/fit/detail/pp.h b/fit/detail/pp.h index 5f96da7..e782171 100644 --- a/fit/detail/pp.h +++ b/fit/detail/pp.h @@ -63,6 +63,8 @@ #define FIT_PP_DEFER(...) __VA_ARGS__ FIT_PP_EMPTY() #define FIT_PP_OBSTRUCT(...) __VA_ARGS__ FIT_PP_DEFER(FIT_PP_EMPTY)() #define FIT_PP_EXPAND(...) __VA_ARGS__ +#define FIT_PP_EAT(...) +#define FIT_PP_REM(...) __VA_ARGS__ #define FIT_PP_IIF(c) FIT_PP_PRIMITIVE_CAT(FIT_PP_IIF_, c) #define FIT_PP_IIF_0(t, ...) __VA_ARGS__ @@ -82,4 +84,5 @@ #define FIT_PP_RAIL_ID() FIT_PP_RAIL + #endif \ No newline at end of file diff --git a/test/builder.cpp b/test/builder.cpp new file mode 100644 index 0000000..be8fb22 --- /dev/null +++ b/test/builder.cpp @@ -0,0 +1,54 @@ +#include +#include +#include "test.h" + +template class Trait, class... Ts> +struct as_integral_constant +{ + typedef Trait::type...> result_type; + typedef std::integral_constant type; +}; + +template class Trait, class... Ts> +constexpr typename as_integral_constant::type +trait(Ts&&...) +{ + return typename as_integral_constant::type(); +} + +template +struct is_integral +: fit::detail::and_...> +{}; + +namespace builder { + +// class +FIT_FUNCTION_CLASS((sum_class)(const auto x, const auto y) if(trait(x, y))(x + y) else (1)) +// object +FIT_FUNCTION_OBJECT((sum)(const auto x, const auto y) if(trait(x, y))(x + y) else (1)) +FIT_FUNCTION_OBJECT((sum2)(const auto x, const int y) if(trait(x))(x + y)) +// pipe +FIT_FUNCTION_PIPE_OBJECT((sum_pipe)(const auto x, const auto y) if(trait(x, y))(x + y) else (1)) + +// // const_value +// FIT_FUNCTION_OBJECT((const_value)(const auto x) if(x == std::integral_constant())(true)) +// FIT_FUNCTION_OBJECT((const_value)(const auto x) if(x == std::integral_constant())(true) else (false)) +// FIT_FUNCTION_OBJECT((const_value2)(const auto x) if(x == std::integral_constant())(true) else if(x == std::integral_constant())(false)) + +} + +struct foo {}; + +FIT_TEST_CASE() +{ + FIT_TEST_CHECK( builder::sum(1, 2) == 3 ); + FIT_TEST_CHECK( builder::sum2(1, 2) == 3 ); + FIT_TEST_CHECK( builder::sum_class()(1, 2) == 3 ); + FIT_TEST_CHECK( (1 | builder::sum_pipe(2)) == 3 ); + FIT_TEST_CHECK( builder::sum(foo(), 2) == 1 ); + // FIT_TEST_CHECK( const_value(std::integral_constant()) ); + // FIT_TEST_CHECK( !const_value(std::integral_constant()) ); + +} +