1 /*=============================================================================
2     Copyright (c) 2016 Lee Clagett
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/container/vector.hpp>
9 #include <boost/fusion/tuple/tuple.hpp>
10 #include <boost/config.hpp>
11 #include <boost/type_traits/is_constructible.hpp>
12 #include <boost/type_traits/is_convertible.hpp>
13 
14 #define FUSION_SEQUENCE boost::fusion::tuple
15 #define FUSION_ALT_SEQUENCE boost::fusion::vector
16 #include "traits.hpp"
17 
18 struct not_convertible {};
19 
20 /*  Some construction differences in fusion::tuple from std::tuple:
21       - Construction from elements cannot call an explicit constructor.
22       - There is no implicit construction from elements.
23       - Construction from std::pair is _enabled_ when tuple is not of size 2.
24       - Construction from tuple is _enabled_ when destination tuple is of
25         different size.
26       - Implicit construction from std::pair can call explicit constructors on
27         elements.
28       - Implicit construction from tuple can call explicit constructors on
29         elements.
30 
31     These differences are historical. Matching the behavior of std::tuple
32     could break existing code, however, switching to fusion::vector would
33     restore the historical behavior. */
34 int
main()35 main()
36 {
37     using namespace boost::fusion;
38 
39     test_convertible(false /* no conversion construction */ );
40 
41     BOOST_TEST((is_convertible<std::pair<int, int>, tuple<int, int> >(true)));
42     BOOST_TEST((
43         is_convertible<std::pair<int, int>, tuple<convertible, int> >(true)
44     ));
45     BOOST_TEST((
46         is_convertible<std::pair<int, int>, tuple<int, convertible> >(true)
47     ));
48     BOOST_TEST((
49         is_convertible<
50             std::pair<int, int>, tuple<convertible, convertible>
51         >(true)
52     ));
53 
54 #if defined(FUSION_TEST_HAS_CONSTRUCTIBLE)
55     test_constructible();
56 
57     BOOST_TEST((is_constructible< tuple<> >(true)));
58     BOOST_TEST((is_constructible<tuple<>, int>(false)));
59 
60     BOOST_TEST((is_constructible< tuple<int> >(true)));
61     BOOST_TEST((is_constructible<tuple<int>, int>(true)));
62     BOOST_TEST((is_constructible<tuple<convertible>, int>(true)));
63     BOOST_TEST((is_constructible<tuple<not_convertible>, int>(false)));
64     BOOST_TEST((is_constructible< tuple<int>, vector<int> >(false)));
65     BOOST_TEST((is_constructible<tuple<int>, int, int>(false)));
66 
67     BOOST_TEST((is_constructible< tuple<int, int> >(true)));
68     // boost::is_constructible always fail to test ctor which takes 2 or more arguments on GCC 4.7.
69 #if !BOOST_WORKAROUND(BOOST_GCC, < 40700)
70     BOOST_TEST((is_constructible<tuple<int, int>, int, int>(true)));
71     BOOST_TEST((
72         is_constructible<tuple<convertible, convertible>, int, int>(true)
73     ));
74 #endif // !(gcc < 4.7)
75     BOOST_TEST((is_constructible<tuple<int, not_convertible>, int, int>(false)));
76     BOOST_TEST((is_constructible<tuple<not_convertible, int>, int, int>(false)));
77     BOOST_TEST((
78         is_constructible<tuple<not_convertible, not_convertible>, int, int>(false)
79     ));
80 #if defined(BOOST_FUSION_HAS_VARIADIC_VECTOR)
81     // C++03 fusion::tuple has constructors that can never be used
82     BOOST_TEST((is_constructible<tuple<int, int>, int>(false)));
83 #endif
84     BOOST_TEST((is_constructible<tuple<int, int>, int, int, int>(false)));
85 
86 #endif // FUSION_TEST_HAS_CONSTRUCTIBLE
87 
88     return boost::report_errors();
89 }
90