1 /*=============================================================================
2 Copyright (c) 1999-2003 Jaakko Jarvi
3 Copyright (c) 2001-2011 Joel de Guzman
4
5 Distributed under the Boost Software License, Version 1.0. (See accompanying
6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 ==============================================================================*/
8 #include <boost/detail/lightweight_test.hpp>
9 #include <boost/fusion/sequence/intrinsic/at.hpp>
10 #include <boost/fusion/sequence/intrinsic/value_at.hpp>
11 #include <boost/static_assert.hpp>
12 #include <iostream>
13
14 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
15 #include <functional>
16 #endif
17
18 #if !defined(FUSION_AT)
19 #define FUSION_AT at_c
20 #endif
21
22 #if !defined(FUSION_VALUE_AT)
23 #define FUSION_VALUE_AT(S, N) boost::fusion::result_of::value_at_c<S, N>
24 #endif
25
26 namespace test_detail
27 {
28 // something to prevent warnings for unused variables
dummy(const T &)29 template<class T> void dummy(const T&) {}
30
31 class A {};
32 }
33
34 void
test()35 test()
36 {
37 using namespace boost::fusion;
38 using namespace test_detail;
39
40 double d = 2.7;
41 A a;
42 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
43 // Note: C++11 will pickup the rvalue overload for the d argument
44 // since we do not have all permutations (expensive!) for all const&
45 // and && arguments. We either have all && or all const& arguments only.
46 // For that matter, use std::ref to disambiguate the call.
47
48 FUSION_SEQUENCE<int, double&, const A&, int> t(1, std::ref(d), a, 2);
49 #else
50 FUSION_SEQUENCE<int, double&, const A&, int> t(1, d, a, 2);
51 #endif
52 const FUSION_SEQUENCE<int, double&, const A, int> ct(t);
53
54 int i = FUSION_AT<0>(t);
55 int i2 = FUSION_AT<3>(t);
56
57 BOOST_TEST(i == 1 && i2 == 2);
58
59 int j = FUSION_AT<0>(ct);
60 BOOST_TEST(j == 1);
61
62 FUSION_AT<0>(t) = 5;
63 BOOST_TEST(FUSION_AT<0>(t) == 5);
64
65 #if defined(FUSION_TEST_FAIL)
66 FUSION_AT<0>(ct) = 5; // can't assign to const
67 #endif
68
69 double e = FUSION_AT<1>(t);
70 BOOST_TEST(e > 2.69 && e < 2.71);
71
72 FUSION_AT<1>(t) = 3.14+i;
73 BOOST_TEST(FUSION_AT<1>(t) > 4.13 && FUSION_AT<1>(t) < 4.15);
74
75 #if defined(FUSION_TEST_FAIL)
76 FUSION_AT<4>(t) = A(); // can't assign to const
77 dummy(FUSION_AT<5>(ct)); // illegal index
78 #endif
79
80 ++FUSION_AT<0>(t);
81 BOOST_TEST(FUSION_AT<0>(t) == 6);
82
83 typedef FUSION_SEQUENCE<int, float> seq_type;
84
85 BOOST_STATIC_ASSERT(!(
86 boost::is_const<FUSION_VALUE_AT(seq_type, 0)::type>::value));
87
88 // constness should not affect
89 BOOST_STATIC_ASSERT(!(
90 boost::is_const<FUSION_VALUE_AT(const seq_type, 0)::type>::value));
91
92 BOOST_STATIC_ASSERT(!(
93 boost::is_const<FUSION_VALUE_AT(seq_type, 1)::type>::value));
94
95 // constness should not affect
96 BOOST_STATIC_ASSERT(!(
97 boost::is_const<FUSION_VALUE_AT(const seq_type, 1)::type>::value));
98
99 dummy(i); dummy(i2); dummy(j); dummy(e); // avoid warns for unused variables
100 }
101