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 8 #include <boost/fusion/sequence/comparison.hpp> 9 #include <boost/mpl/identity.hpp> 10 11 namespace test_detail 12 { 13 struct convertible 14 { convertibletest_detail::convertible15 convertible() : value_() {} convertibletest_detail::convertible16 convertible(int value) : value_(value) {} 17 int value_; 18 }; 19 operator ==(convertible const & lhs,convertible const & rhs)20 bool operator==(convertible const& lhs, convertible const& rhs) 21 { 22 return lhs.value_ == rhs.value_; 23 } 24 operator !=(convertible const & lhs,convertible const & rhs)25 bool operator!=(convertible const& lhs, convertible const& rhs) 26 { 27 return lhs.value_ != rhs.value_; 28 } 29 30 // Testing conversion at function call allows for testing mutable lvalue, 31 // const lvalue, and rvalue as the source. mpl::identity prevents deduction 32 template <typename T> implicit_construct(typename boost::mpl::identity<T>::type source)33 T implicit_construct(typename boost::mpl::identity<T>::type source) 34 { 35 return source; 36 } 37 38 template <typename F, typename Source, typename Expected> run(Source const & source,Expected const & expected)39 bool run(Source const& source, Expected const& expected) 40 { 41 return F()(source, expected); 42 } 43 44 template <typename F, typename Source> run(Source const & source)45 bool run(Source const& source) 46 { 47 return run<F>(source, source); 48 } 49 50 template <typename T> 51 struct can_rvalue_implicit_construct 52 { 53 template<typename Source, typename Expected> operator ()test_detail::can_rvalue_implicit_construct54 bool operator()(Source const& source, Expected const& expected) const 55 { 56 return expected == implicit_construct<T>(implicit_construct<Source>(source)); 57 } 58 }; 59 60 template <typename T> 61 struct can_lvalue_implicit_construct 62 { 63 template <typename Source, typename Expected> operator ()test_detail::can_lvalue_implicit_construct64 bool operator()(Source source, Expected const& expected) const 65 { 66 return expected == implicit_construct<T>(source); 67 } 68 }; 69 70 template <typename T> 71 struct can_const_lvalue_implicit_construct 72 { 73 template <typename Source, typename Expected> operator ()test_detail::can_const_lvalue_implicit_construct74 bool operator()(Source const& source, Expected const& expected) const 75 { 76 return expected == implicit_construct<T>(source); 77 } 78 }; 79 80 template <typename T> 81 struct can_implicit_construct 82 { 83 template <typename Source, typename Expected> operator ()test_detail::can_implicit_construct84 bool operator()(Source const& source, Expected const& expected) const 85 { 86 return 87 run< can_rvalue_implicit_construct<T> >(source, expected) && 88 run< can_lvalue_implicit_construct<T> >(source, expected) && 89 run< can_const_lvalue_implicit_construct<T> >(source, expected); 90 } 91 }; 92 93 template <typename T> 94 struct can_rvalue_construct 95 { 96 template<typename Source, typename Expected> operator ()test_detail::can_rvalue_construct97 bool operator()(Source const& source, Expected const& expected) const 98 { 99 return expected == T(implicit_construct<Source>(source)); 100 } 101 }; 102 103 template <typename T> 104 struct can_lvalue_construct 105 { 106 template <typename Source, typename Expected> operator ()test_detail::can_lvalue_construct107 bool operator()(Source source, Expected const& expected) const 108 { 109 return expected == T(source); 110 } 111 }; 112 113 template <typename T> 114 struct can_const_lvalue_construct 115 { 116 template <typename Source, typename Expected> operator ()test_detail::can_const_lvalue_construct117 bool operator()(Source const& source, Expected const& expected) const 118 { 119 return expected == T(source); 120 } 121 }; 122 123 template <typename T> 124 struct can_construct 125 { 126 template <typename Source, typename Expected> operator ()test_detail::can_construct127 bool operator()(Source const& source, Expected const& expected) const 128 { 129 return 130 run< can_rvalue_construct<T> >(source, expected) && 131 run< can_lvalue_construct<T> >(source, expected) && 132 run< can_const_lvalue_construct<T> >(source, expected); 133 } 134 }; 135 136 template <typename T> 137 struct can_rvalue_assign 138 { 139 template <typename Source, typename Expected> operator ()test_detail::can_rvalue_assign140 bool operator()(Source const& source, Expected const& expected) const 141 { 142 bool result = true; 143 { 144 T seq; 145 result &= (seq == expected || seq != expected); 146 147 seq = implicit_construct<Source>(source); 148 result &= (seq == expected); 149 } 150 return result; 151 } 152 }; 153 154 template <typename T> 155 struct can_lvalue_assign 156 { 157 158 template <typename Source, typename Expected> operator ()test_detail::can_lvalue_assign159 bool operator()(Source source, Expected const& expected) const 160 { 161 bool result = true; 162 { 163 T seq; 164 result &= (seq == expected || seq != expected); 165 166 seq = source; 167 result &= (seq == expected); 168 } 169 return result; 170 } 171 }; 172 173 template <typename T> 174 struct can_const_lvalue_assign 175 { 176 template <typename Source, typename Expected> operator ()test_detail::can_const_lvalue_assign177 bool operator()(Source const& source, Expected const& expected) const 178 { 179 bool result = true; 180 { 181 T seq; 182 result &= (seq == expected || seq != expected); 183 184 seq = source; 185 result &= (seq == expected); 186 } 187 return result; 188 } 189 }; 190 191 template <typename T> 192 struct can_assign 193 { 194 template <typename Source, typename Expected> operator ()test_detail::can_assign195 bool operator()(Source const& source, Expected const& expected) const 196 { 197 return 198 run< can_rvalue_assign<T> >(source, expected) && 199 run< can_lvalue_assign<T> >(source, expected) && 200 run< can_const_lvalue_assign<T> >(source, expected); 201 } 202 }; 203 204 template <typename T> 205 struct can_copy 206 { 207 template <typename Source, typename Expected> operator ()test_detail::can_copy208 bool operator()(Source const& source, Expected const& expected) const 209 { 210 return 211 run< can_construct<T> >(source, expected) && 212 run< can_implicit_construct<T> >(source, expected) && 213 run< can_assign<T> >(source, expected); 214 } 215 }; 216 } // test_detail 217