parameterized_inheritance.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. // Copyright Cromwell D. Enage 2018.
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. #include <boost/parameter/config.hpp>
  6. #if !defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING) && \
  7. (BOOST_PARAMETER_COMPOSE_MAX_ARITY < 3)
  8. #error Define BOOST_PARAMETER_COMPOSE_MAX_ARITY as 3 or greater.
  9. #endif
  10. #include <boost/parameter/name.hpp>
  11. namespace test {
  12. BOOST_PARAMETER_NAME(a0)
  13. BOOST_PARAMETER_NAME(a1)
  14. BOOST_PARAMETER_NAME(a2)
  15. }
  16. #if !defined(BOOST_NO_SFINAE)
  17. #include <boost/parameter/is_argument_pack.hpp>
  18. #include <boost/type_traits/is_convertible.hpp>
  19. #include <boost/core/enable_if.hpp>
  20. #endif
  21. namespace test {
  22. #if !defined(BOOST_NO_SFINAE)
  23. struct _enabler
  24. {
  25. };
  26. #endif
  27. template <typename T>
  28. class backend0
  29. {
  30. T _a0;
  31. public:
  32. template <typename ArgPack>
  33. explicit backend0(
  34. ArgPack const& args
  35. #if !defined(BOOST_NO_SFINAE)
  36. , typename boost::enable_if<
  37. boost::parameter::is_argument_pack<ArgPack>
  38. , test::_enabler
  39. >::type = test::_enabler()
  40. #endif
  41. ) : _a0(args[test::_a0])
  42. {
  43. }
  44. #if !defined(BOOST_NO_SFINAE)
  45. template <typename U>
  46. backend0(
  47. backend0<U> const& copy
  48. , typename boost::enable_if<
  49. boost::is_convertible<U,T>
  50. , test::_enabler
  51. >::type = test::_enabler()
  52. ) : _a0(copy.get_a0())
  53. {
  54. }
  55. #endif
  56. template <typename Iterator>
  57. backend0(Iterator itr, Iterator itr_end) : _a0(itr, itr_end)
  58. {
  59. }
  60. T const& get_a0() const
  61. {
  62. return this->_a0;
  63. }
  64. protected:
  65. template <typename ArgPack>
  66. void initialize_impl(ArgPack const& args)
  67. {
  68. this->_a0 = args[test::_a0];
  69. }
  70. };
  71. template <typename B, typename T>
  72. class backend1 : public B
  73. {
  74. T _a1;
  75. public:
  76. template <typename ArgPack>
  77. explicit backend1(
  78. ArgPack const& args
  79. #if !defined(BOOST_NO_SFINAE)
  80. , typename boost::enable_if<
  81. boost::parameter::is_argument_pack<ArgPack>
  82. , test::_enabler
  83. >::type = test::_enabler()
  84. #endif
  85. ) : B(args), _a1(args[test::_a1])
  86. {
  87. }
  88. #if !defined(BOOST_NO_SFINAE)
  89. template <typename Derived>
  90. backend1(
  91. Derived const& copy
  92. , typename boost::disable_if<
  93. boost::parameter::is_argument_pack<Derived>
  94. , test::_enabler
  95. >::type = test::_enabler()
  96. ) : B(copy), _a1(copy.get_a1())
  97. {
  98. }
  99. #endif
  100. T const& get_a1() const
  101. {
  102. return this->_a1;
  103. }
  104. protected:
  105. template <typename ArgPack>
  106. void initialize_impl(ArgPack const& args)
  107. {
  108. B::initialize_impl(args);
  109. this->_a1 = args[test::_a1];
  110. }
  111. };
  112. template <typename B, typename T>
  113. class backend2 : public B
  114. {
  115. T _a2;
  116. public:
  117. template <typename ArgPack>
  118. explicit backend2(
  119. ArgPack const& args
  120. #if !defined(BOOST_NO_SFINAE)
  121. , typename boost::enable_if<
  122. boost::parameter::is_argument_pack<ArgPack>
  123. , test::_enabler
  124. >::type = test::_enabler()
  125. #endif
  126. ) : B(args), _a2(args[test::_a2])
  127. {
  128. }
  129. #if !defined(BOOST_NO_SFINAE)
  130. template <typename Derived>
  131. backend2(
  132. Derived const& copy
  133. , typename boost::disable_if<
  134. boost::parameter::is_argument_pack<Derived>
  135. , test::_enabler
  136. >::type = test::_enabler()
  137. ) : B(copy), _a2(copy.get_a2())
  138. {
  139. }
  140. #endif
  141. T const& get_a2() const
  142. {
  143. return this->_a2;
  144. }
  145. protected:
  146. template <typename ArgPack>
  147. void initialize_impl(ArgPack const& args)
  148. {
  149. B::initialize_impl(args);
  150. this->_a2 = args[test::_a2];
  151. }
  152. };
  153. }
  154. #include <boost/parameter/preprocessor_no_spec.hpp>
  155. #if !defined(BOOST_NO_SFINAE)
  156. #include <boost/parameter/are_tagged_arguments.hpp>
  157. #endif
  158. namespace test {
  159. template <typename B>
  160. struct frontend : public B
  161. {
  162. BOOST_PARAMETER_NO_SPEC_CONSTRUCTOR(frontend, (B))
  163. #if !defined(BOOST_NO_SFINAE)
  164. template <typename Iterator>
  165. frontend(
  166. Iterator itr
  167. , Iterator itr_end
  168. , typename boost::disable_if<
  169. boost::parameter::are_tagged_arguments<Iterator>
  170. , test::_enabler
  171. >::type = test::_enabler()
  172. ) : B(itr, itr_end)
  173. {
  174. }
  175. template <typename O>
  176. frontend(frontend<O> const& copy) : B(copy)
  177. {
  178. }
  179. #endif
  180. BOOST_PARAMETER_NO_SPEC_MEMBER_FUNCTION((void), initialize)
  181. {
  182. this->initialize_impl(args);
  183. }
  184. BOOST_PARAMETER_NO_SPEC_FUNCTION_CALL_OPERATOR((void))
  185. {
  186. this->initialize_impl(args);
  187. }
  188. };
  189. } // namespace test
  190. #include <boost/core/lightweight_test.hpp>
  191. #if !defined(BOOST_NO_SFINAE)
  192. #include <string>
  193. #endif
  194. int main()
  195. {
  196. char const* p = "foo";
  197. char const* q = "bar";
  198. test::frontend<
  199. test::backend2<test::backend1<test::backend0<char const*>, char>, int>
  200. > composed_obj0(test::_a2 = 4, test::_a1 = ' ', test::_a0 = p);
  201. #if defined(BOOST_NO_SFINAE)
  202. test::frontend<
  203. test::backend1<test::backend2<test::backend0<char const*>, int>, char>
  204. > composed_obj1(test::_a0 = p, test::_a1 = ' ', test::_a2 = 4);
  205. #else
  206. test::frontend<
  207. test::backend1<test::backend2<test::backend0<char const*>, int>, char>
  208. > composed_obj1(composed_obj0);
  209. #endif
  210. BOOST_TEST_EQ(composed_obj0.get_a0(), composed_obj1.get_a0());
  211. BOOST_TEST_EQ(composed_obj0.get_a1(), composed_obj1.get_a1());
  212. BOOST_TEST_EQ(composed_obj0.get_a2(), composed_obj1.get_a2());
  213. composed_obj0.initialize(test::_a0 = q, test::_a1 = '!', test::_a2 = 8);
  214. composed_obj1.initialize(test::_a2 = 8, test::_a1 = '!', test::_a0 = q);
  215. BOOST_TEST_EQ(composed_obj0.get_a0(), composed_obj1.get_a0());
  216. BOOST_TEST_EQ(composed_obj0.get_a1(), composed_obj1.get_a1());
  217. BOOST_TEST_EQ(composed_obj0.get_a2(), composed_obj1.get_a2());
  218. composed_obj0(test::_a2 = 8, test::_a1 = '!', test::_a0 = q);
  219. composed_obj1(test::_a0 = q, test::_a1 = '!', test::_a2 = 8);
  220. BOOST_TEST_EQ(composed_obj0.get_a0(), composed_obj1.get_a0());
  221. BOOST_TEST_EQ(composed_obj0.get_a1(), composed_obj1.get_a1());
  222. BOOST_TEST_EQ(composed_obj0.get_a2(), composed_obj1.get_a2());
  223. #if !defined(BOOST_NO_SFINAE)
  224. test::frontend<test::backend0<std::string> > string_wrap(p, p + 3);
  225. BOOST_TEST_EQ(string_wrap.get_a0(), std::string(p));
  226. #endif
  227. return boost::report_errors();
  228. }