summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/parameter/test/sfinae.cpp
blob: 17c50443f62163c03c6fdb875437c21219f41f7f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
// Copyright David Abrahams, Daniel Wallin 2003.
// 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)

#include <boost/parameter/config.hpp>

#if (BOOST_PARAMETER_MAX_ARITY < 2)
#error Define BOOST_PARAMETER_MAX_ARITY as 2 or greater.
#endif
#if !defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
#if (BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY < 3)
#error Define BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY \
as 3 or greater.
#endif
#endif

#include <boost/parameter/name.hpp>

namespace test {

    BOOST_PARAMETER_NAME((name, keywords) in(name))
    BOOST_PARAMETER_NAME((value, keywords) in(value))
} // namespace test

#if defined(BOOST_PARAMETER_CAN_USE_MP11)
#include <type_traits>
#else
#include <boost/mpl/bool.hpp>
#include <boost/mpl/if.hpp>
#include <boost/type_traits/is_convertible.hpp>
#endif

namespace test {

    template <typename To>
    struct f_predicate
    {
        template <typename From, typename Args>
#if defined(BOOST_PARAMETER_CAN_USE_MP11)
        using fn = std::is_convertible<From,To>;
#else
        struct apply
          : boost::mpl::if_<
                boost::is_convertible<From,To>
              , boost::mpl::true_
              , boost::mpl::false_
            >
        {
        };
#endif
    };
} // namespace test

#include <boost/parameter/parameters.hpp>
#include <boost/parameter/optional.hpp>
#include <string>

namespace test {

    struct f_parameters
      : boost::parameter::parameters<
            boost::parameter::optional<
                test::keywords::name
              , test::f_predicate<std::string>
            >
          , boost::parameter::optional<
                test::keywords::value
              , test::f_predicate<float>
            >
        >
    {
    };
} // namespace test

#include <boost/core/lightweight_test.hpp>

namespace test {

    // The use of assert_equal_string is just a nasty workaround for a
    // vc++ 6 ICE.
    void assert_equal_string(std::string x, std::string y)
    {
        BOOST_TEST(x == y);
    }

    template <typename P>
    void f_impl(P const& p)
    {
        float v = p[test::value | 3.f];
        BOOST_TEST_EQ(v, 3.f);
        test::assert_equal_string(p[test::name | "bar"], "foo");
    }

    void f()
    {
        test::f_impl(f_parameters()());
    }
} // namespace test

#include <boost/parameter/match.hpp>

namespace test {

    template <typename A0>
    void
        f(
            A0 const& a0
          , BOOST_PARAMETER_MATCH(f_parameters, (A0), args)
        )
    {
        test::f_impl(args(a0));
    }

    template <typename A0, typename A1>
    void
        f(
            A0 const& a0
          , A1 const& a1
          , BOOST_PARAMETER_MATCH(f_parameters, (A0)(A1), args)
        )
    {
        test::f_impl(args(a0, a1));
    }
} // namespace test

#if !defined(BOOST_NO_SFINAE) && \
    !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592))
#include <boost/core/enable_if.hpp>

#if !defined(BOOST_PARAMETER_CAN_USE_MP11)
#include <boost/type_traits/is_same.hpp>
#endif

namespace test {

    // On compilers that actually support SFINAE, add another overload that is
    // an equally good match and can only be in the overload set when the
    // others are not.  This tests that the SFINAE is actually working.  On
    // all other compilers we're just checking that everything about
    // SFINAE-enabled code will work, except of course the SFINAE.
    template <typename A0, typename A1>
    typename boost::enable_if<
#if defined(BOOST_PARAMETER_CAN_USE_MP11)
        std::is_same<int,A0>
#else
        typename boost::mpl::if_<
            boost::is_same<int,A0>
          , boost::mpl::true_
          , boost::mpl::false_
        >::type
#endif
      , int
    >::type
        f(A0 const& a0, A1 const& a1)
    {
        return 0;
    }
} // namespace test

#endif  // SFINAE enabled, no Borland workarounds needed.

int main()
{
    test::f("foo");
    test::f("foo", 3.f);
    test::f(test::value = 3.f, test::name = "foo");
#if !defined(BOOST_NO_SFINAE) && \
    !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592))
    BOOST_TEST_EQ(0, test::f(3, 4));
#endif
    return boost::report_errors();
}