sfinae.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. // Copyright David Abrahams, Daniel Wallin 2003.
  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 (BOOST_PARAMETER_MAX_ARITY < 2)
  7. #error Define BOOST_PARAMETER_MAX_ARITY as 2 or greater.
  8. #endif
  9. #if !defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
  10. #if (BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY < 3)
  11. #error Define BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY \
  12. as 3 or greater.
  13. #endif
  14. #endif
  15. #include <boost/parameter/name.hpp>
  16. namespace test {
  17. BOOST_PARAMETER_NAME((name, keywords) in(name))
  18. BOOST_PARAMETER_NAME((value, keywords) in(value))
  19. } // namespace test
  20. #if defined(BOOST_PARAMETER_CAN_USE_MP11)
  21. #include <type_traits>
  22. #else
  23. #include <boost/mpl/bool.hpp>
  24. #include <boost/mpl/if.hpp>
  25. #include <boost/type_traits/is_convertible.hpp>
  26. #endif
  27. namespace test {
  28. template <typename To>
  29. struct f_predicate
  30. {
  31. template <typename From, typename Args>
  32. #if defined(BOOST_PARAMETER_CAN_USE_MP11)
  33. using fn = std::is_convertible<From,To>;
  34. #else
  35. struct apply
  36. : boost::mpl::if_<
  37. boost::is_convertible<From,To>
  38. , boost::mpl::true_
  39. , boost::mpl::false_
  40. >
  41. {
  42. };
  43. #endif
  44. };
  45. } // namespace test
  46. #include <boost/parameter/parameters.hpp>
  47. #include <boost/parameter/optional.hpp>
  48. #include <string>
  49. namespace test {
  50. struct f_parameters
  51. : boost::parameter::parameters<
  52. boost::parameter::optional<
  53. test::keywords::name
  54. , test::f_predicate<std::string>
  55. >
  56. , boost::parameter::optional<
  57. test::keywords::value
  58. , test::f_predicate<float>
  59. >
  60. >
  61. {
  62. };
  63. } // namespace test
  64. #include <boost/core/lightweight_test.hpp>
  65. namespace test {
  66. // The use of assert_equal_string is just a nasty workaround for a
  67. // vc++ 6 ICE.
  68. void assert_equal_string(std::string x, std::string y)
  69. {
  70. BOOST_TEST(x == y);
  71. }
  72. template <typename P>
  73. void f_impl(P const& p)
  74. {
  75. float v = p[test::value | 3.f];
  76. BOOST_TEST_EQ(v, 3.f);
  77. test::assert_equal_string(p[test::name | "bar"], "foo");
  78. }
  79. void f()
  80. {
  81. test::f_impl(f_parameters()());
  82. }
  83. } // namespace test
  84. #include <boost/parameter/match.hpp>
  85. namespace test {
  86. template <typename A0>
  87. void
  88. f(
  89. A0 const& a0
  90. , BOOST_PARAMETER_MATCH(f_parameters, (A0), args)
  91. )
  92. {
  93. test::f_impl(args(a0));
  94. }
  95. template <typename A0, typename A1>
  96. void
  97. f(
  98. A0 const& a0
  99. , A1 const& a1
  100. , BOOST_PARAMETER_MATCH(f_parameters, (A0)(A1), args)
  101. )
  102. {
  103. test::f_impl(args(a0, a1));
  104. }
  105. } // namespace test
  106. #if !defined(BOOST_NO_SFINAE) && \
  107. !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592))
  108. #include <boost/core/enable_if.hpp>
  109. #if !defined(BOOST_PARAMETER_CAN_USE_MP11)
  110. #include <boost/type_traits/is_same.hpp>
  111. #endif
  112. namespace test {
  113. // On compilers that actually support SFINAE, add another overload that is
  114. // an equally good match and can only be in the overload set when the
  115. // others are not. This tests that the SFINAE is actually working. On
  116. // all other compilers we're just checking that everything about
  117. // SFINAE-enabled code will work, except of course the SFINAE.
  118. template <typename A0, typename A1>
  119. typename boost::enable_if<
  120. #if defined(BOOST_PARAMETER_CAN_USE_MP11)
  121. std::is_same<int,A0>
  122. #else
  123. typename boost::mpl::if_<
  124. boost::is_same<int,A0>
  125. , boost::mpl::true_
  126. , boost::mpl::false_
  127. >::type
  128. #endif
  129. , int
  130. >::type
  131. f(A0 const& a0, A1 const& a1)
  132. {
  133. return 0;
  134. }
  135. } // namespace test
  136. #endif // SFINAE enabled, no Borland workarounds needed.
  137. int main()
  138. {
  139. test::f("foo");
  140. test::f("foo", 3.f);
  141. test::f(test::value = 3.f, test::name = "foo");
  142. #if !defined(BOOST_NO_SFINAE) && \
  143. !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592))
  144. BOOST_TEST_EQ(0, test::f(3, 4));
  145. #endif
  146. return boost::report_errors();
  147. }