1 /*=============================================================================
2     Copyright (c) 2001-2009 Joel de Guzman
3 
4     Distributed under the Boost Software License, Version 1.0. (See accompanying
5     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 ==============================================================================*/
7 #include <boost/detail/lightweight_test.hpp>
8 #include <boost/fusion/adapted/adt/adapt_adt.hpp>
9 #include <boost/fusion/sequence/intrinsic/at.hpp>
10 #include <boost/fusion/sequence/intrinsic/size.hpp>
11 #include <boost/fusion/sequence/intrinsic/empty.hpp>
12 #include <boost/fusion/sequence/intrinsic/front.hpp>
13 #include <boost/fusion/sequence/intrinsic/back.hpp>
14 #include <boost/fusion/sequence/intrinsic/value_at.hpp>
15 #include <boost/fusion/sequence/io/out.hpp>
16 #include <boost/fusion/container/vector/vector.hpp>
17 #include <boost/fusion/container/list/list.hpp>
18 #include <boost/fusion/container/generation/make_vector.hpp>
19 #include <boost/fusion/container/vector/convert.hpp>
20 #include <boost/fusion/sequence/comparison/equal_to.hpp>
21 #include <boost/fusion/sequence/comparison/not_equal_to.hpp>
22 #include <boost/fusion/sequence/comparison/less.hpp>
23 #include <boost/fusion/sequence/comparison/less_equal.hpp>
24 #include <boost/fusion/sequence/comparison/greater.hpp>
25 #include <boost/fusion/sequence/comparison/greater_equal.hpp>
26 #include <boost/fusion/mpl.hpp>
27 #include <boost/fusion/support/is_view.hpp>
28 #include <boost/mpl/front.hpp>
29 #include <boost/mpl/is_sequence.hpp>
30 #include <boost/mpl/assert.hpp>
31 #include <boost/type_traits/is_same.hpp>
32 #include <iostream>
33 #include <string>
34 
35 namespace ns
36 {
37     class point
38     {
39     public:
40 
point()41         point() : x(0), y(0), z(0) {}
point(int in_x,int in_y,int in_z)42         point(int in_x, int in_y, int in_z) : x(in_x), y(in_y), z(in_z) {}
43 
get_x() const44         int get_x() const { return x; }
get_y() const45         int get_y() const { return y; }
get_z() const46         int get_z() const { return z; }
set_x(int x_)47         void set_x(int x_) { x = x_; }
set_y(int y_)48         void set_y(int y_) { y = y_; }
set_z(int z_)49         void set_z(int z_) { z = z_; }
50 
51     private:
52 
53         int x;
54         int y;
55         int z;
56     };
57 
58 #if !BOOST_WORKAROUND(__GNUC__,<4)
59     class point_with_private_members
60     {
61         friend struct boost::fusion::extension::access;
62 
63     public:
point_with_private_members()64         point_with_private_members() : x(0), y(0), z(0) {}
point_with_private_members(int in_x,int in_y,int in_z)65         point_with_private_members(int in_x, int in_y, int in_z)
66           : x(in_x), y(in_y), z(in_z) {}
67 
get_x() const68         int get_x() const { return x; }
get_y() const69         int get_y() const { return y; }
get_z() const70         int get_z() const { return z; }
set_x(int x_)71         void set_x(int x_) { x = x_; }
set_y(int y_)72         void set_y(int y_) { y = y_; }
set_z(int z_)73         void set_z(int z_) { z = z_; }
74 
75     private:
76 
77         int x;
78         int y;
79         int z;
80     };
81 #endif
82 
83     // A sequence that has data members defined in an unrelated namespace
84     // (std, in this case). This allows testing ADL issues.
85     class name
86     {
87     public:
name()88         name() {}
name(const std::string & last,const std::string & first)89         name(const std::string& last, const std::string& first)
90            : last(last), first(first) {}
91 
get_last() const92         const std::string& get_last() const { return last; }
get_first() const93         const std::string& get_first() const { return first; }
set_last(const std::string & last_)94         void set_last(const std::string& last_) { last = last_; }
set_first(const std::string & first_)95         void set_first(const std::string& first_) { first = first_; }
96     private:
97         std::string last;
98         std::string first;
99     };
100 }
101 
102 #if BOOST_PP_VARIADICS
103   BOOST_FUSION_ADAPT_ADT(
104       ns::point,
105       (int, int, obj.get_x(), obj.set_x(val))
106       // Mixing auto & BOOST_FUSION_ADAPT_AUTO to test backward compatibility
107       (auto, BOOST_FUSION_ADAPT_AUTO, obj.get_y(), obj.set_y(val))
108       (obj.get_z(), obj.set_z(val))
109   )
110 
111 #   if !BOOST_WORKAROUND(__GNUC__,<4)
112     BOOST_FUSION_ADAPT_ADT(
113         ns::point_with_private_members,
114         (obj.get_x(), obj.set_x(val))
115         (obj.get_y(), obj.set_y(val))
116         (obj.get_z(), obj.set_z(val))
117     )
118 #   endif
119 
120 
121   BOOST_FUSION_ADAPT_ADT(
122       ns::name,
123       (obj.get_last(), obj.set_last(val))
124       (obj.get_first(), obj.set_first(val))
125   )
126 
127 
128 #else // BOOST_PP_VARIADICS
129   BOOST_FUSION_ADAPT_ADT(
130       ns::point,
131       (int, int, obj.get_x(), obj.set_x(val))
132       (auto, auto, obj.get_y(), obj.set_y(val))
133       (auto, auto, obj.get_z(), obj.set_z(val))
134   )
135 
136 #   if !BOOST_WORKAROUND(__GNUC__,<4)
137     BOOST_FUSION_ADAPT_ADT(
138         ns::point_with_private_members,
139         (auto, auto, obj.get_x(), obj.set_x(val))
140         (auto, auto, obj.get_y(), obj.set_y(val))
141         (auto, auto, obj.get_z(), obj.set_z(val))
142     )
143 #   endif
144 
145   BOOST_FUSION_ADAPT_ADT(
146       ns::name,
147       (const std::string&, const std::string&, obj.get_last(), obj.set_last(val))
148       (BOOST_FUSION_ADAPT_AUTO, auto, obj.get_first(), obj.set_first(val))
149   )
150 
151 #endif
152 
153 class empty_adt{};
154 BOOST_FUSION_ADAPT_ADT(empty_adt,)
155 
156 int
main()157 main()
158 {
159     using namespace boost::fusion;
160     using namespace boost;
161 
162     std::cout << tuple_open('[');
163     std::cout << tuple_close(']');
164     std::cout << tuple_delimiter(", ");
165 
166     {
167         BOOST_MPL_ASSERT_NOT((traits::is_view<ns::point>));
168         BOOST_STATIC_ASSERT(!traits::is_view<ns::point>::value);
169         ns::point p(123, 456, 789);
170 
171         std::cout << at_c<0>(p) << std::endl;
172         std::cout << at_c<1>(p) << std::endl;
173         std::cout << at_c<2>(p) << std::endl;
174         std::cout << p << std::endl;
175         BOOST_TEST(p == make_vector(123, 456, 789));
176 
177         at_c<0>(p) = 6;
178         at_c<1>(p) = 9;
179         at_c<2>(p) = 12;
180         BOOST_TEST(p == make_vector(6, 9, 12));
181 
182         BOOST_STATIC_ASSERT(boost::fusion::result_of::size<ns::point>::value == 3);
183         BOOST_STATIC_ASSERT(!boost::fusion::result_of::empty<ns::point>::value);
184 
185         BOOST_TEST(front(p) == 6);
186         BOOST_TEST(back(p) == 12);
187     }
188 
189     {
190         fusion::vector<int, float, int> v1(4, 2.f, 2);
191         ns::point v2(5, 3, 3);
192         fusion::vector<long, double, int> v3(5, 4., 4);
193         BOOST_TEST(v1 < v2);
194         BOOST_TEST(v1 <= v2);
195         BOOST_TEST(v2 > v1);
196         BOOST_TEST(v2 >= v1);
197         BOOST_TEST(v2 < v3);
198         BOOST_TEST(v2 <= v3);
199         BOOST_TEST(v3 > v2);
200         BOOST_TEST(v3 >= v2);
201     }
202 
203     {
204         fusion::vector<std::string, std::string> v1("Lincoln", "Abraham");
205         ns::name v2("Roosevelt", "Franklin");
206         ns::name v3("Roosevelt", "Theodore");
207         BOOST_TEST(v1 < v2);
208         BOOST_TEST(v1 <= v2);
209         BOOST_TEST(v2 > v1);
210         BOOST_TEST(v2 >= v1);
211         BOOST_TEST(v2 < v3);
212         BOOST_TEST(v2 <= v3);
213         BOOST_TEST(v3 > v2);
214         BOOST_TEST(v3 >= v2);
215     }
216 
217     {
218         // conversion from ns::point to vector
219         ns::point p(5, 3, 3);
220         fusion::vector<int, long, int> v(p);
221         v = p;
222     }
223 
224     {
225         // conversion from ns::point to list
226         ns::point p(5, 3, 3);
227         fusion::list<int, long, int> l(p);
228         l = p;
229     }
230 
231     {
232         BOOST_MPL_ASSERT((mpl::is_sequence<ns::point>));
233         BOOST_MPL_ASSERT((boost::is_same<
234             boost::fusion::result_of::value_at_c<ns::point,0>::type
235           , mpl::front<ns::point>::type>));
236     }
237 
238 #if !BOOST_WORKAROUND(__GNUC__,<4)
239     {
240         BOOST_MPL_ASSERT_NOT((traits::is_view<ns::point_with_private_members>));
241         BOOST_STATIC_ASSERT(!traits::is_view<ns::point_with_private_members>::value);
242         ns::point_with_private_members p(123, 456, 789);
243 
244         std::cout << at_c<0>(p) << std::endl;
245         std::cout << at_c<1>(p) << std::endl;
246         std::cout << at_c<2>(p) << std::endl;
247         std::cout << p << std::endl;
248         BOOST_TEST(p == make_vector(123, 456, 789));
249 
250         at_c<0>(p) = 6;
251         at_c<1>(p) = 9;
252         at_c<2>(p) = 12;
253         BOOST_TEST(p == make_vector(6, 9, 12));
254 
255         BOOST_STATIC_ASSERT(boost::fusion::result_of::size<ns::point_with_private_members>::value == 3);
256         BOOST_STATIC_ASSERT(!boost::fusion::result_of::empty<ns::point_with_private_members>::value);
257 
258         BOOST_TEST(front(p) == 6);
259         BOOST_TEST(back(p) == 12);
260     }
261 #endif
262 
263     {
264         // Check types provided in case it's provided
265         BOOST_MPL_ASSERT((
266             boost::is_same<
267                 boost::fusion::result_of::front<ns::point>::type,
268                 boost::fusion::extension::adt_attribute_proxy<ns::point,0,false>
269             >));
270         BOOST_MPL_ASSERT((
271             boost::is_same<
272                 boost::fusion::result_of::front<ns::point>::type::type,
273                 int
274             >));
275         BOOST_MPL_ASSERT((
276             boost::is_same<
277                 boost::fusion::result_of::front<ns::point const>::type,
278                 boost::fusion::extension::adt_attribute_proxy<ns::point,0,true>
279             >));
280         BOOST_MPL_ASSERT((
281             boost::is_same<
282                 boost::fusion::result_of::front<ns::point const>::type::type,
283                 int
284             >));
285 
286         // Check types provided in case it's deduced
287         BOOST_MPL_ASSERT((
288             boost::is_same<
289                 boost::fusion::result_of::back<ns::point>::type,
290                 boost::fusion::extension::adt_attribute_proxy<ns::point,2,false>
291             >));
292         BOOST_MPL_ASSERT((
293             boost::is_same<
294                 boost::fusion::result_of::back<ns::point>::type::type,
295                 int
296             >));
297         BOOST_MPL_ASSERT((
298             boost::is_same<
299                 boost::fusion::result_of::back<ns::point const>::type,
300                 boost::fusion::extension::adt_attribute_proxy<ns::point,2,true>
301             >));
302         BOOST_MPL_ASSERT((
303             boost::is_same<
304                 boost::fusion::result_of::back<ns::point const>::type::type,
305                 int
306             >));
307     }
308 
309     return boost::report_errors();
310 }
311 
312