preprocessor_deduced.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. // Copyright Daniel Wallin 2006.
  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. #include <boost/parameter/preprocessor.hpp>
  7. #include <boost/parameter/name.hpp>
  8. #include <boost/tuple/tuple.hpp>
  9. #include <map>
  10. #include <string>
  11. #include "basics.hpp"
  12. #if defined(BOOST_PARAMETER_CAN_USE_MP11)
  13. #include <boost/parameter/value_type.hpp>
  14. #include <boost/mp11/map.hpp>
  15. #include <boost/core/enable_if.hpp>
  16. #include <type_traits>
  17. #else
  18. #include <boost/mpl/bool.hpp>
  19. #include <boost/mpl/if.hpp>
  20. #include <boost/type_traits/is_convertible.hpp>
  21. #if !defined(BOOST_NO_SFINAE)
  22. #include <boost/parameter/value_type.hpp>
  23. #include <boost/mpl/has_key.hpp>
  24. #include <boost/core/enable_if.hpp>
  25. #include <boost/type_traits/is_same.hpp>
  26. #endif
  27. #endif
  28. namespace test {
  29. BOOST_PARAMETER_NAME(expected)
  30. BOOST_PARAMETER_NAME(x)
  31. BOOST_PARAMETER_NAME(y)
  32. BOOST_PARAMETER_NAME(z)
  33. #if defined(BOOST_PARAMETER_CAN_USE_MP11)
  34. template <typename To>
  35. struct predicate
  36. {
  37. template <typename From, typename Args>
  38. using fn = std::is_convertible<From,To>;
  39. };
  40. BOOST_PARAMETER_FUNCTION((int), f, test::tag,
  41. (required
  42. (expected, *)
  43. )
  44. (deduced
  45. (required
  46. (x, *(test::predicate<int>))
  47. (y, *(test::predicate<std::string>))
  48. )
  49. )
  50. )
  51. #else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
  52. struct predicate_int
  53. {
  54. template <typename From, typename Args>
  55. struct apply
  56. : boost::mpl::if_<
  57. boost::is_convertible<From,int>
  58. , boost::mpl::true_
  59. , boost::mpl::false_
  60. >
  61. {
  62. };
  63. };
  64. struct predicate_string
  65. {
  66. template <typename From, typename Args>
  67. struct apply
  68. : boost::mpl::if_<
  69. boost::is_convertible<From,std::string>
  70. , boost::mpl::true_
  71. , boost::mpl::false_
  72. >
  73. {
  74. };
  75. };
  76. BOOST_PARAMETER_FUNCTION((int), f, test::tag,
  77. (required
  78. (expected, *)
  79. )
  80. (deduced
  81. (required
  82. (x, *(test::predicate_int))
  83. (y, *(test::predicate_string))
  84. )
  85. )
  86. )
  87. #endif // BOOST_PARAMETER_CAN_USE_MP11
  88. {
  89. BOOST_TEST(test::equal(x, boost::tuples::get<0>(expected)));
  90. BOOST_TEST(test::equal(y, boost::tuples::get<1>(expected)));
  91. return 1;
  92. }
  93. struct X
  94. {
  95. X(int x_ = -1) : x(x_)
  96. {
  97. }
  98. bool operator==(X const& other) const
  99. {
  100. return this->x == other.x;
  101. }
  102. int x;
  103. };
  104. #if defined(BOOST_PARAMETER_CAN_USE_MP11)
  105. BOOST_PARAMETER_FUNCTION((int), g, test::tag,
  106. (required
  107. (expected, *)
  108. )
  109. (deduced
  110. (required
  111. (x, *(test::predicate<int>))
  112. (y, *(test::predicate<std::string>))
  113. )
  114. (optional
  115. (z, *(test::predicate<test::X>), test::X())
  116. )
  117. )
  118. )
  119. #else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
  120. struct predicate_X
  121. {
  122. template <typename From, typename Args>
  123. struct apply
  124. : boost::mpl::if_<
  125. boost::is_convertible<From,test::X>
  126. , boost::mpl::true_
  127. , boost::mpl::false_
  128. >
  129. {
  130. };
  131. };
  132. BOOST_PARAMETER_FUNCTION((int), g, tag,
  133. (required
  134. (expected, *)
  135. )
  136. (deduced
  137. (required
  138. (x, *(test::predicate_int))
  139. (y, *(test::predicate_string))
  140. )
  141. (optional
  142. (z, *(test::predicate_X), test::X())
  143. )
  144. )
  145. )
  146. #endif // BOOST_PARAMETER_CAN_USE_MP11
  147. {
  148. BOOST_TEST(test::equal(x, boost::tuples::get<0>(expected)));
  149. BOOST_TEST(test::equal(y, boost::tuples::get<1>(expected)));
  150. BOOST_TEST(test::equal(z, boost::tuples::get<2>(expected)));
  151. return 1;
  152. }
  153. #if defined(BOOST_PARAMETER_CAN_USE_MP11)
  154. BOOST_PARAMETER_FUNCTION((int), sfinae, test::tag,
  155. (deduced
  156. (required
  157. (x, *(test::predicate<std::string>))
  158. )
  159. )
  160. )
  161. #else
  162. BOOST_PARAMETER_FUNCTION((int), sfinae, test::tag,
  163. (deduced
  164. (required
  165. (x, *(test::predicate_string))
  166. )
  167. )
  168. )
  169. #endif
  170. {
  171. return 1;
  172. }
  173. #if !defined(BOOST_NO_SFINAE)
  174. // On compilers that actually support SFINAE, add another overload
  175. // that is an equally good match and can only be in the overload set
  176. // when the others are not. This tests that the SFINAE is actually
  177. // working. On all other compilers we're just checking that everything
  178. // about SFINAE-enabled code will work, except of course the SFINAE.
  179. template <typename A0>
  180. typename boost::enable_if<
  181. #if defined(BOOST_PARAMETER_CAN_USE_MP11)
  182. std::is_same<int,A0>
  183. #else
  184. typename boost::mpl::if_<
  185. boost::is_same<int,A0>
  186. , boost::mpl::true_
  187. , boost::mpl::false_
  188. >::type
  189. #endif
  190. , int
  191. >::type
  192. sfinae(A0 const& a0)
  193. {
  194. return 0;
  195. }
  196. #if defined(LIBS_PARAMETER_TEST_COMPILE_FAILURE_VENDOR_SPECIFIC) || \
  197. !BOOST_WORKAROUND(BOOST_MSVC, < 1800)
  198. // Test support for two different Boost.Parameter-enabled
  199. // function call operator overloads.
  200. class char_read_base
  201. {
  202. int index;
  203. char const* key;
  204. public:
  205. template <typename Args>
  206. explicit char_read_base(Args const& args)
  207. : index(args[test::_y]), key(args[test::_z])
  208. {
  209. }
  210. BOOST_PARAMETER_FUNCTION_CALL_OPERATOR((void), test::tag,
  211. (deduced
  212. (required
  213. (y, (int))
  214. (z, (char const*))
  215. )
  216. )
  217. )
  218. {
  219. this->index = y;
  220. this->key = z;
  221. }
  222. BOOST_PARAMETER_CONST_FUNCTION_CALL_OPERATOR((char), test::tag,
  223. (deduced
  224. (required
  225. (y, (bool))
  226. (z, (std::map<char const*,std::string>))
  227. )
  228. )
  229. )
  230. {
  231. return y ? (
  232. (z.find(this->key)->second)[this->index]
  233. ) : this->key[this->index];
  234. }
  235. };
  236. struct char_reader : public char_read_base
  237. {
  238. BOOST_PARAMETER_CONSTRUCTOR(char_reader, (char_read_base), test::tag,
  239. (deduced
  240. (required
  241. (y, (int))
  242. (z, (char const*))
  243. )
  244. )
  245. )
  246. };
  247. #endif // MSVC-11.0-
  248. // Test Boost.Parameter-enabled functions
  249. // with parameter-dependent return types.
  250. #if !defined(LIBS_PARAMETER_TEST_COMPILE_FAILURE)
  251. #if defined(BOOST_PARAMETER_CAN_USE_MP11)
  252. BOOST_PARAMETER_FUNCTION(
  253. (
  254. boost::lazy_enable_if<
  255. boost::mp11::mp_map_contains<Args,test::tag::y>
  256. , boost::parameter::value_type<Args,test::tag::y>
  257. >
  258. ), return_y, test::tag,
  259. (deduced
  260. (required
  261. (x, (std::map<char const*,std::string>))
  262. (y, (char const*))
  263. )
  264. (optional
  265. (z, (int), 4)
  266. )
  267. )
  268. )
  269. #else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
  270. BOOST_PARAMETER_FUNCTION(
  271. (
  272. boost::lazy_enable_if<
  273. typename boost::mpl::has_key<Args,test::tag::y>::type
  274. , boost::parameter::value_type<Args,test::tag::y>
  275. >
  276. ), return_y, test::tag,
  277. (deduced
  278. (required
  279. (x, (std::map<char const*,std::string>))
  280. (y, (char const*))
  281. )
  282. (optional
  283. (z, (int), 4)
  284. )
  285. )
  286. )
  287. #endif // BOOST_PARAMETER_CAN_USE_MP11
  288. {
  289. return y;
  290. }
  291. #endif // LIBS_PARAMETER_TEST_COMPILE_FAILURE
  292. #endif // BOOST_NO_SFINAE
  293. #if defined(LIBS_PARAMETER_TEST_COMPILE_FAILURE)
  294. BOOST_PARAMETER_FUNCTION(
  295. (typename boost::parameter::value_type<Args,test::tag::y>::type),
  296. return_y, test::tag,
  297. (deduced
  298. (required
  299. (x, (std::map<char const*,std::string>))
  300. (y, (char const*))
  301. )
  302. (optional
  303. (z, (int), 4)
  304. )
  305. )
  306. )
  307. {
  308. return y;
  309. }
  310. #endif // defined(LIBS_PARAMETER_TEST_COMPILE_FAILURE)
  311. } // namespace test
  312. #include <boost/core/lightweight_test.hpp>
  313. int main()
  314. {
  315. test::f(
  316. boost::make_tuple(0, std::string("foo"))
  317. , test::_x = 0
  318. , test::_y = std::string("foo")
  319. );
  320. test::f(
  321. boost::make_tuple(0, std::string("foo"))
  322. , 0
  323. , std::string("foo")
  324. );
  325. test::f(
  326. boost::make_tuple(0, std::string("foo"))
  327. , std::string("foo")
  328. , 0
  329. );
  330. test::f(
  331. boost::make_tuple(0, std::string("foo"))
  332. , test::_y = std::string("foo")
  333. , 0
  334. );
  335. test::f(
  336. boost::make_tuple(0, std::string("foo"))
  337. , test::_x = 0
  338. , std::string("foo")
  339. );
  340. test::f(
  341. boost::make_tuple(0, std::string("foo"))
  342. , 0
  343. , test::_y = std::string("foo")
  344. );
  345. test::g(
  346. boost::make_tuple(0, std::string("foo"), test::X())
  347. , test::_x = 0
  348. , test::_y = std::string("foo")
  349. );
  350. test::g(
  351. boost::make_tuple(0, std::string("foo"), test::X())
  352. , 0
  353. , std::string("foo")
  354. );
  355. test::g(
  356. boost::make_tuple(0, std::string("foo"), test::X())
  357. , std::string("foo")
  358. , 0
  359. );
  360. test::g(
  361. boost::make_tuple(0, std::string("foo"), test::X())
  362. , test::_y = std::string("foo")
  363. , 0
  364. );
  365. test::g(
  366. boost::make_tuple(0, std::string("foo"), test::X())
  367. , test::_x = 0
  368. , std::string("foo")
  369. );
  370. test::g(
  371. boost::make_tuple(0, std::string("foo"), test::X())
  372. , 0
  373. , test::_y = std::string("foo")
  374. );
  375. test::g(
  376. boost::make_tuple(0, std::string("foo"), test::X(1))
  377. , 0
  378. , test::_y = std::string("foo")
  379. , test::X(1)
  380. );
  381. test::g(
  382. boost::make_tuple(0, std::string("foo"), test::X(1))
  383. , test::X(1)
  384. , 0
  385. , test::_y = std::string("foo")
  386. );
  387. std::map<char const*,std::string> k2s;
  388. #if !defined(BOOST_NO_SFINAE)
  389. char const* keys[] = {"foo", "bar", "baz"};
  390. BOOST_TEST_EQ(1, test::sfinae(keys[0]));
  391. BOOST_TEST_EQ(0, test::sfinae(0));
  392. #if defined(LIBS_PARAMETER_TEST_COMPILE_FAILURE_VENDOR_SPECIFIC) || \
  393. !BOOST_WORKAROUND(BOOST_MSVC, < 1800)
  394. k2s[keys[0]] = std::string("qux");
  395. k2s[keys[1]] = std::string("wmb");
  396. k2s[keys[2]] = std::string("zxc");
  397. test::char_reader r(keys[0], 0);
  398. BOOST_TEST_EQ('q', (r(k2s, true)));
  399. BOOST_TEST_EQ('f', (r(k2s, false)));
  400. r(keys[1], 1);
  401. BOOST_TEST_EQ('m', (r(k2s, true)));
  402. BOOST_TEST_EQ('a', (r(k2s, false)));
  403. r(keys[2], 2);
  404. BOOST_TEST_EQ('c', (r(k2s, true)));
  405. BOOST_TEST_EQ('z', (r(k2s, false)));
  406. #endif // MSVC-11.0-
  407. #if !defined(LIBS_PARAMETER_TEST_COMPILE_FAILURE)
  408. BOOST_TEST_EQ(keys[1], test::return_y(2, k2s, keys[1]));
  409. #endif
  410. #endif // BOOST_NO_SFINAE
  411. #if defined(LIBS_PARAMETER_TEST_COMPILE_FAILURE)
  412. BOOST_TEST_EQ(keys[1], test::return_y(2, k2s, keys[1]));
  413. #endif
  414. return boost::report_errors();
  415. }