Go to the documentation of this file. 1 #ifndef SILICIUM_TRAIT_HPP
2 #define SILICIUM_TRAIT_HPP
5 #include <boost/preprocessor/repetition/repeat_from_to.hpp>
6 #include <boost/preprocessor/seq/for_each.hpp>
7 #include <boost/preprocessor/array/size.hpp>
8 #include <boost/preprocessor/array/elem.hpp>
9 #include <boost/preprocessor/enum_params.hpp>
11 #if SILICIUM_COMPILER_GENERATES_MOVES
12 # define SILICIUM_MOVABLE_MEMBER(struct_name, member_name) \
13 struct_name() = default; \
14 SILICIUM_DEFAULT_MOVE(struct_name)
16 # define SILICIUM_MOVABLE_MEMBER(struct_name, member_name) \
17 struct_name() : member_name() BOOST_NOEXCEPT {} \
18 struct_name(struct_name &&other) BOOST_NOEXCEPT : member_name(std::move(other.member_name)) {} \
19 struct_name &operator = (struct_name &&other) BOOST_NOEXCEPT { member_name = std::move(other.member_name); return *this; }
22 #define SILICIUM_DETAIL_MAKE_PARAMETER(z, n, array) BOOST_PP_COMMA_IF(n) BOOST_PP_ARRAY_ELEM(n, array) BOOST_PP_CAT(arg, n)
23 #define SILICIUM_DETAIL_MAKE_PARAMETERS(array) ( BOOST_PP_REPEAT(BOOST_PP_ARRAY_SIZE(array), SILICIUM_DETAIL_MAKE_PARAMETER, array) )
25 #define SILICIUM_DETAIL_MAKE_PURE_VIRTUAL_METHOD(r, data, elem) \
27 BOOST_PP_TUPLE_ELEM(4, 2, elem) \
28 BOOST_PP_TUPLE_ELEM(4, 0, elem) \
29 SILICIUM_DETAIL_MAKE_PARAMETERS(BOOST_PP_TUPLE_ELEM(4, 1, elem)) \
30 BOOST_PP_TUPLE_ELEM(4, 3, elem) \
33 #define SILICIUM_DETAIL_MAKE_INTERFACE(name, typedefs, methods) struct name { \
36 BOOST_PP_SEQ_FOR_EACH(SILICIUM_DETAIL_MAKE_PURE_VIRTUAL_METHOD, _, methods) \
39 #define SILICIUM_DETAIL_ERASER_METHOD_ARGUMENT(z, n, text) , BOOST_PP_CAT(_, n)
41 #define SILICIUM_DETAIL_MAKE_ERASER_METHOD(r, data, elem) \
43 BOOST_PP_TUPLE_ELEM(4, 2, elem) \
44 BOOST_PP_TUPLE_ELEM(4, 0, elem) \
45 SILICIUM_DETAIL_MAKE_PARAMETERS(BOOST_PP_TUPLE_ELEM(4, 1, elem)) \
46 BOOST_PP_TUPLE_ELEM(4, 3, elem) \
48 return original. BOOST_PP_TUPLE_ELEM(4, 0, elem) ( \
49 BOOST_PP_ENUM_PARAMS(BOOST_PP_ARRAY_SIZE(BOOST_PP_TUPLE_ELEM(4, 1, elem)), arg) \
53 #define SILICIUM_DETAIL_MAKE_BOX_METHOD(r, data, elem) \
54 BOOST_PP_TUPLE_ELEM(4, 2, elem) \
55 BOOST_PP_TUPLE_ELEM(4, 0, elem) \
56 SILICIUM_DETAIL_MAKE_PARAMETERS(BOOST_PP_TUPLE_ELEM(4, 1, elem)) \
57 BOOST_PP_TUPLE_ELEM(4, 3, elem) { \
59 return original -> BOOST_PP_TUPLE_ELEM(4, 0, elem) ( \
60 BOOST_PP_ENUM_PARAMS(BOOST_PP_ARRAY_SIZE(BOOST_PP_TUPLE_ELEM(4, 1, elem)), arg) \
64 #define SILICIUM_DETAIL_MAKE_ERASER(name, typedefs, methods) template <class Original> struct name : interface { \
67 SILICIUM_MOVABLE_MEMBER(name, original) \
68 explicit name(Original original) : original(std::move(original)) {} \
69 BOOST_PP_SEQ_FOR_EACH(SILICIUM_DETAIL_MAKE_ERASER_METHOD, _, methods) \
72 #define SILICIUM_DETAIL_MAKE_BOX(name, typedefs, methods) struct box { \
74 std::unique_ptr<interface> original; \
75 SILICIUM_MOVABLE_MEMBER(name, original) \
76 explicit name(std::unique_ptr<interface> original) BOOST_NOEXCEPT : original(std::move(original)) {} \
77 BOOST_PP_SEQ_FOR_EACH(SILICIUM_DETAIL_MAKE_BOX_METHOD, _, methods) \
80 #define SILICIUM_SPECIALIZED_TRAIT(name, specialization, typedefs, methods) struct name specialization { \
81 SILICIUM_DETAIL_MAKE_INTERFACE(interface, typedefs, methods) \
82 SILICIUM_DETAIL_MAKE_ERASER(eraser, typedefs, methods) \
83 SILICIUM_DETAIL_MAKE_BOX(box, typedefs, methods) \
84 template <class Original> \
85 static eraser<typename std::decay<Original>::type> erase(Original &&original) { \
86 return eraser<typename std::decay<Original>::type>{std::forward<Original>(original)}; \
88 template <class Original> \
89 static box make_box(Original &&original) { \
90 return box{Si::to_unique(erase(std::forward<Original>(original)))}; \
94 #define SILICIUM_TRAIT(name, methods) SILICIUM_SPECIALIZED_TRAIT(name, , , methods)
96 #define SILICIUM_TRAIT_WITH_TYPEDEFS(name, typedefs, methods) SILICIUM_SPECIALIZED_TRAIT(name, , typedefs, methods)