1 | // Copyright Daniel Wallin 2006. Use, modification and distribution is |
---|
2 | // subject to the Boost Software License, Version 1.0. (See accompanying |
---|
3 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
---|
4 | |
---|
5 | #include <boost/parameter/preprocessor.hpp> |
---|
6 | #include <boost/parameter/name.hpp> |
---|
7 | #include <boost/type_traits/is_convertible.hpp> |
---|
8 | #include <boost/tuple/tuple.hpp> |
---|
9 | #include <string> |
---|
10 | #include "basics.hpp" |
---|
11 | |
---|
12 | #ifndef BOOST_NO_SFINAE |
---|
13 | # include <boost/utility/enable_if.hpp> |
---|
14 | #endif |
---|
15 | |
---|
16 | namespace test { |
---|
17 | |
---|
18 | namespace mpl = boost::mpl; |
---|
19 | |
---|
20 | using mpl::_; |
---|
21 | using boost::is_convertible; |
---|
22 | |
---|
23 | BOOST_PARAMETER_NAME(expected) |
---|
24 | BOOST_PARAMETER_NAME(x) |
---|
25 | BOOST_PARAMETER_NAME(y) |
---|
26 | BOOST_PARAMETER_NAME(z) |
---|
27 | |
---|
28 | // Sun has problems with this syntax: |
---|
29 | // |
---|
30 | // template1< r* ( template2<x> ) > |
---|
31 | // |
---|
32 | // Workaround: factor template2<x> into a separate typedef |
---|
33 | typedef is_convertible<_, int> predicate1; |
---|
34 | typedef is_convertible<_, std::string> predicate2; |
---|
35 | |
---|
36 | #if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x580)) |
---|
37 | |
---|
38 | BOOST_PARAMETER_FUNCTION((int), f, tag, |
---|
39 | (required |
---|
40 | (expected, *) |
---|
41 | ) |
---|
42 | (deduced |
---|
43 | (required |
---|
44 | (x, *(predicate1)) |
---|
45 | (y, *(predicate2)) |
---|
46 | ) |
---|
47 | ) |
---|
48 | ) |
---|
49 | #else |
---|
50 | BOOST_PARAMETER_FUNCTION((int), f, tag, |
---|
51 | (required |
---|
52 | (expected, *) |
---|
53 | ) |
---|
54 | (deduced |
---|
55 | (required |
---|
56 | (x, *(is_convertible<_, int>)) |
---|
57 | (y, *(is_convertible<_, std::string>)) |
---|
58 | ) |
---|
59 | ) |
---|
60 | ) |
---|
61 | #endif |
---|
62 | { |
---|
63 | assert(equal(x, boost::tuples::get<0>(expected))); |
---|
64 | assert(equal(y, boost::tuples::get<1>(expected))); |
---|
65 | return 1; |
---|
66 | } |
---|
67 | |
---|
68 | struct X |
---|
69 | { |
---|
70 | X(int x = -1) |
---|
71 | : x(x) |
---|
72 | {} |
---|
73 | |
---|
74 | bool operator==(X const& other) const |
---|
75 | { |
---|
76 | return x == other.x; |
---|
77 | } |
---|
78 | |
---|
79 | int x; |
---|
80 | }; |
---|
81 | |
---|
82 | typedef is_convertible<_, X> predicate3; // SunPro workaround; see above |
---|
83 | |
---|
84 | BOOST_PARAMETER_FUNCTION((int), g, tag, |
---|
85 | (required |
---|
86 | (expected, *) |
---|
87 | ) |
---|
88 | (deduced |
---|
89 | (required |
---|
90 | (x, *(is_convertible<_, int>)) |
---|
91 | (y, *(is_convertible<_, std::string>)) |
---|
92 | ) |
---|
93 | (optional |
---|
94 | (z, *(predicate3), X()) |
---|
95 | ) |
---|
96 | ) |
---|
97 | ) |
---|
98 | { |
---|
99 | assert(equal(x, boost::tuples::get<0>(expected))); |
---|
100 | assert(equal(y, boost::tuples::get<1>(expected))); |
---|
101 | assert(equal(z, boost::tuples::get<2>(expected))); |
---|
102 | return 1; |
---|
103 | } |
---|
104 | |
---|
105 | BOOST_PARAMETER_FUNCTION( |
---|
106 | (int), sfinae, tag, |
---|
107 | (deduced |
---|
108 | (required |
---|
109 | (x, *(predicate2)) |
---|
110 | ) |
---|
111 | ) |
---|
112 | ) |
---|
113 | { |
---|
114 | return 1; |
---|
115 | } |
---|
116 | |
---|
117 | #ifndef BOOST_NO_SFINAE |
---|
118 | // On compilers that actually support SFINAE, add another overload |
---|
119 | // that is an equally good match and can only be in the overload set |
---|
120 | // when the others are not. This tests that the SFINAE is actually |
---|
121 | // working. On all other compilers we're just checking that |
---|
122 | // everything about SFINAE-enabled code will work, except of course |
---|
123 | // the SFINAE. |
---|
124 | template<class A0> |
---|
125 | typename boost::enable_if<boost::is_same<int,A0>, int>::type |
---|
126 | sfinae(A0 const& a0) |
---|
127 | { |
---|
128 | return 0; |
---|
129 | } |
---|
130 | #endif |
---|
131 | |
---|
132 | } // namespace test |
---|
133 | |
---|
134 | using boost::make_tuple; |
---|
135 | |
---|
136 | // make_tuple doesn't work with char arrays. |
---|
137 | char const* str(char const* s) |
---|
138 | { |
---|
139 | return s; |
---|
140 | } |
---|
141 | |
---|
142 | int main() |
---|
143 | { |
---|
144 | using namespace test; |
---|
145 | |
---|
146 | f(make_tuple(0, str("foo")), _x = 0, _y = "foo"); |
---|
147 | f(make_tuple(0, str("foo")), _x = 0, _y = "foo"); |
---|
148 | f(make_tuple(0, str("foo")), 0, "foo"); |
---|
149 | f(make_tuple(0, str("foo")), "foo", 0); |
---|
150 | f(make_tuple(0, str("foo")), _y = "foo", 0); |
---|
151 | f(make_tuple(0, str("foo")), _x = 0, "foo"); |
---|
152 | f(make_tuple(0, str("foo")), 0, _y = "foo"); |
---|
153 | |
---|
154 | g(make_tuple(0, str("foo"), X()), _x = 0, _y = "foo"); |
---|
155 | g(make_tuple(0, str("foo"), X()), 0, "foo"); |
---|
156 | g(make_tuple(0, str("foo"), X()), "foo", 0); |
---|
157 | g(make_tuple(0, str("foo"), X()), _y = "foo", 0); |
---|
158 | g(make_tuple(0, str("foo"), X()), _x = 0, "foo"); |
---|
159 | g(make_tuple(0, str("foo"), X()), 0, _y = "foo"); |
---|
160 | |
---|
161 | g(make_tuple(0, str("foo"), X(1)), 0, _y = "foo", X(1)); |
---|
162 | g(make_tuple(0, str("foo"), X(1)), X(1), 0, _y = "foo"); |
---|
163 | |
---|
164 | #ifndef BOOST_NO_SFINAE |
---|
165 | assert(sfinae("foo") == 1); |
---|
166 | assert(sfinae(0) == 0); |
---|
167 | #endif |
---|
168 | |
---|
169 | return 0; |
---|
170 | } |
---|
171 | |
---|