1 //===----------------------------------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is dual licensed under the MIT and the University of Illinois Open 6 // Source Licenses. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 // UNSUPPORTED: c++98, c++03, c++11 11 12 // <experimental/tuple> 13 14 // template <class F, class T> constexpr decltype(auto) apply(F &&, T &&) 15 16 // Testing extended function types. The extended function types are those 17 // named by INVOKE but that are not actual callable objects. These include 18 // bullets 1-4 of invoke. 19 20 #include <experimental/tuple> 21 #include <array> 22 #include <utility> 23 #include <cassert> 24 25 // std::array is explicitly allowed to be initialized with A a = { init-list };. 26 // Disable the missing braces warning for this reason. 27 #include "disable_missing_braces_warning.h" 28 29 int count = 0; 30 31 struct A_int_0 32 { 33 A_int_0() : obj1(0){} 34 A_int_0(int x) : obj1(x) {} 35 int mem1() { return ++count; } 36 int mem2() const { return ++count; } 37 int const obj1; 38 }; 39 40 struct A_int_1 41 { 42 A_int_1() {} 43 A_int_1(int) {} 44 int mem1(int x) { return count += x; } 45 int mem2(int x) const { return count += x; } 46 }; 47 48 struct A_int_2 49 { 50 A_int_2() {} 51 A_int_2(int) {} 52 int mem1(int x, int y) { return count += (x + y); } 53 int mem2(int x, int y) const { return count += (x + y); } 54 }; 55 56 template <class A> 57 struct A_wrap 58 { 59 A_wrap() {} 60 A_wrap(int x) : m_a(x) {} 61 A & operator*() { return m_a; } 62 A const & operator*() const { return m_a; } 63 A m_a; 64 }; 65 66 typedef A_wrap<A_int_0> A_wrap_0; 67 typedef A_wrap<A_int_1> A_wrap_1; 68 typedef A_wrap<A_int_2> A_wrap_2; 69 70 71 template <class A> 72 struct A_base : public A 73 { 74 A_base() : A() {} 75 A_base(int x) : A(x) {} 76 }; 77 78 typedef A_base<A_int_0> A_base_0; 79 typedef A_base<A_int_1> A_base_1; 80 typedef A_base<A_int_2> A_base_2; 81 82 namespace ex = std::experimental; 83 84 template < 85 class Tuple, class ConstTuple 86 , class TuplePtr, class ConstTuplePtr 87 , class TupleWrap, class ConstTupleWrap 88 , class TupleBase, class ConstTupleBase 89 > 90 void test_ext_int_0() 91 { 92 count = 0; 93 typedef A_int_0 T; 94 typedef A_wrap_0 Wrap; 95 typedef A_base_0 Base; 96 97 typedef int(T::*mem1_t)(); 98 mem1_t mem1 = &T::mem1; 99 100 typedef int(T::*mem2_t)() const; 101 mem2_t mem2 = &T::mem2; 102 103 typedef int const T::*obj1_t; 104 obj1_t obj1 = &T::obj1; 105 106 // member function w/ref 107 { 108 T a; 109 Tuple t{a}; 110 assert(1 == ex::apply(mem1, t)); 111 assert(count == 1); 112 } 113 count = 0; 114 // member function w/pointer 115 { 116 T a; 117 TuplePtr t{&a}; 118 assert(1 == ex::apply(mem1, t)); 119 assert(count == 1); 120 } 121 count = 0; 122 // member function w/base 123 { 124 Base a; 125 TupleBase t{a}; 126 assert(1 == ex::apply(mem1, t)); 127 assert(count == 1); 128 } 129 count = 0; 130 // member function w/wrap 131 { 132 Wrap a; 133 TupleWrap t{a}; 134 assert(1 == ex::apply(mem1, t)); 135 assert(count == 1); 136 } 137 count = 0; 138 // const member function w/ref 139 { 140 T const a; 141 ConstTuple t{a}; 142 assert(1 == ex::apply(mem2, t)); 143 assert(count == 1); 144 } 145 count = 0; 146 // const member function w/pointer 147 { 148 T const a; 149 ConstTuplePtr t{&a}; 150 assert(1 == ex::apply(mem2, t)); 151 assert(count == 1); 152 } 153 count = 0; 154 // const member function w/base 155 { 156 Base const a; 157 ConstTupleBase t{a}; 158 assert(1 == ex::apply(mem2, t)); 159 assert(count == 1); 160 } 161 count = 0; 162 // const member function w/wrapper 163 { 164 Wrap const a; 165 ConstTupleWrap t{a}; 166 assert(1 == ex::apply(mem2, t)); 167 assert(1 == count); 168 } 169 // member object w/ref 170 { 171 T a{42}; 172 Tuple t{a}; 173 assert(42 == ex::apply(obj1, t)); 174 } 175 // member object w/pointer 176 { 177 T a{42}; 178 TuplePtr t{&a}; 179 assert(42 == ex::apply(obj1, t)); 180 } 181 // member object w/base 182 { 183 Base a{42}; 184 TupleBase t{a}; 185 assert(42 == ex::apply(obj1, t)); 186 } 187 // member object w/wrapper 188 { 189 Wrap a{42}; 190 TupleWrap t{a}; 191 assert(42 == ex::apply(obj1, t)); 192 } 193 } 194 195 196 template < 197 class Tuple, class ConstTuple 198 , class TuplePtr, class ConstTuplePtr 199 , class TupleWrap, class ConstTupleWrap 200 , class TupleBase, class ConstTupleBase 201 > 202 void test_ext_int_1() 203 { 204 count = 0; 205 typedef A_int_1 T; 206 typedef A_wrap_1 Wrap; 207 typedef A_base_1 Base; 208 209 typedef int(T::*mem1_t)(int); 210 mem1_t mem1 = &T::mem1; 211 212 typedef int(T::*mem2_t)(int) const; 213 mem2_t mem2 = &T::mem2; 214 215 // member function w/ref 216 { 217 T a; 218 Tuple t{a, 2}; 219 assert(2 == ex::apply(mem1, t)); 220 assert(count == 2); 221 } 222 count = 0; 223 // member function w/pointer 224 { 225 T a; 226 TuplePtr t{&a, 3}; 227 assert(3 == ex::apply(mem1, t)); 228 assert(count == 3); 229 } 230 count = 0; 231 // member function w/base 232 { 233 Base a; 234 TupleBase t{a, 4}; 235 assert(4 == ex::apply(mem1, t)); 236 assert(count == 4); 237 } 238 count = 0; 239 // member function w/wrap 240 { 241 Wrap a; 242 TupleWrap t{a, 5}; 243 assert(5 == ex::apply(mem1, t)); 244 assert(count == 5); 245 } 246 count = 0; 247 // const member function w/ref 248 { 249 T const a; 250 ConstTuple t{a, 6}; 251 assert(6 == ex::apply(mem2, t)); 252 assert(count == 6); 253 } 254 count = 0; 255 // const member function w/pointer 256 { 257 T const a; 258 ConstTuplePtr t{&a, 7}; 259 assert(7 == ex::apply(mem2, t)); 260 assert(count == 7); 261 } 262 count = 0; 263 // const member function w/base 264 { 265 Base const a; 266 ConstTupleBase t{a, 8}; 267 assert(8 == ex::apply(mem2, t)); 268 assert(count == 8); 269 } 270 count = 0; 271 // const member function w/wrapper 272 { 273 Wrap const a; 274 ConstTupleWrap t{a, 9}; 275 assert(9 == ex::apply(mem2, t)); 276 assert(9 == count); 277 } 278 } 279 280 281 template < 282 class Tuple, class ConstTuple 283 , class TuplePtr, class ConstTuplePtr 284 , class TupleWrap, class ConstTupleWrap 285 , class TupleBase, class ConstTupleBase 286 > 287 void test_ext_int_2() 288 { 289 count = 0; 290 typedef A_int_2 T; 291 typedef A_wrap_2 Wrap; 292 typedef A_base_2 Base; 293 294 typedef int(T::*mem1_t)(int, int); 295 mem1_t mem1 = &T::mem1; 296 297 typedef int(T::*mem2_t)(int, int) const; 298 mem2_t mem2 = &T::mem2; 299 300 // member function w/ref 301 { 302 T a; 303 Tuple t{a, 1, 1}; 304 assert(2 == ex::apply(mem1, t)); 305 assert(count == 2); 306 } 307 count = 0; 308 // member function w/pointer 309 { 310 T a; 311 TuplePtr t{&a, 1, 2}; 312 assert(3 == ex::apply(mem1, t)); 313 assert(count == 3); 314 } 315 count = 0; 316 // member function w/base 317 { 318 Base a; 319 TupleBase t{a, 2, 2}; 320 assert(4 == ex::apply(mem1, t)); 321 assert(count == 4); 322 } 323 count = 0; 324 // member function w/wrap 325 { 326 Wrap a; 327 TupleWrap t{a, 2, 3}; 328 assert(5 == ex::apply(mem1, t)); 329 assert(count == 5); 330 } 331 count = 0; 332 // const member function w/ref 333 { 334 T const a; 335 ConstTuple t{a, 3, 3}; 336 assert(6 == ex::apply(mem2, t)); 337 assert(count == 6); 338 } 339 count = 0; 340 // const member function w/pointer 341 { 342 T const a; 343 ConstTuplePtr t{&a, 3, 4}; 344 assert(7 == ex::apply(mem2, t)); 345 assert(count == 7); 346 } 347 count = 0; 348 // const member function w/base 349 { 350 Base const a; 351 ConstTupleBase t{a, 4, 4}; 352 assert(8 == ex::apply(mem2, t)); 353 assert(count == 8); 354 } 355 count = 0; 356 // const member function w/wrapper 357 { 358 Wrap const a; 359 ConstTupleWrap t{a, 4, 5}; 360 assert(9 == ex::apply(mem2, t)); 361 assert(9 == count); 362 } 363 } 364 365 int main() 366 { 367 { 368 test_ext_int_0< 369 std::tuple<A_int_0 &>, std::tuple<A_int_0 const &> 370 , std::tuple<A_int_0 *>, std::tuple<A_int_0 const *> 371 , std::tuple<A_wrap_0 &>, std::tuple<A_wrap_0 const &> 372 , std::tuple<A_base_0 &>, std::tuple<A_base_0 const &> 373 >(); 374 test_ext_int_0< 375 std::tuple<A_int_0>, std::tuple<A_int_0 const> 376 , std::tuple<A_int_0 *>, std::tuple<A_int_0 const *> 377 , std::tuple<A_wrap_0>, std::tuple<A_wrap_0 const> 378 , std::tuple<A_base_0>, std::tuple<A_base_0 const> 379 >(); 380 test_ext_int_0< 381 std::array<A_int_0, 1>, std::array<A_int_0 const, 1> 382 , std::array<A_int_0*, 1>, std::array<A_int_0 const*, 1> 383 , std::array<A_wrap_0, 1>, std::array<A_wrap_0 const, 1> 384 , std::array<A_base_0, 1>, std::array<A_base_0 const, 1> 385 >(); 386 } 387 { 388 test_ext_int_1< 389 std::tuple<A_int_1 &, int>, std::tuple<A_int_1 const &, int> 390 , std::tuple<A_int_1 *, int>, std::tuple<A_int_1 const *, int> 391 , std::tuple<A_wrap_1 &, int>, std::tuple<A_wrap_1 const &, int> 392 , std::tuple<A_base_1 &, int>, std::tuple<A_base_1 const &, int> 393 >(); 394 test_ext_int_1< 395 std::tuple<A_int_1, int>, std::tuple<A_int_1 const, int> 396 , std::tuple<A_int_1 *, int>, std::tuple<A_int_1 const *, int> 397 , std::tuple<A_wrap_1, int>, std::tuple<A_wrap_1 const, int> 398 , std::tuple<A_base_1, int>, std::tuple<A_base_1 const, int> 399 >(); 400 test_ext_int_1< 401 std::pair<A_int_1 &, int>, std::pair<A_int_1 const &, int> 402 , std::pair<A_int_1 *, int>, std::pair<A_int_1 const *, int> 403 , std::pair<A_wrap_1 &, int>, std::pair<A_wrap_1 const &, int> 404 , std::pair<A_base_1 &, int>, std::pair<A_base_1 const &, int> 405 >(); 406 test_ext_int_1< 407 std::pair<A_int_1, int>, std::pair<A_int_1 const, int> 408 , std::pair<A_int_1 *, int>, std::pair<A_int_1 const *, int> 409 , std::pair<A_wrap_1, int>, std::pair<A_wrap_1 const, int> 410 , std::pair<A_base_1, int>, std::pair<A_base_1 const, int> 411 >(); 412 } 413 { 414 test_ext_int_2< 415 std::tuple<A_int_2 &, int, int>, std::tuple<A_int_2 const &, int, int> 416 , std::tuple<A_int_2 *, int, int>, std::tuple<A_int_2 const *, int, int> 417 , std::tuple<A_wrap_2 &, int, int>, std::tuple<A_wrap_2 const &, int, int> 418 , std::tuple<A_base_2 &, int, int>, std::tuple<A_base_2 const &, int, int> 419 >(); 420 test_ext_int_2< 421 std::tuple<A_int_2, int, int>, std::tuple<A_int_2 const, int, int> 422 , std::tuple<A_int_2 *, int, int>, std::tuple<A_int_2 const *, int, int> 423 , std::tuple<A_wrap_2, int, int>, std::tuple<A_wrap_2 const, int, int> 424 , std::tuple<A_base_2, int, int>, std::tuple<A_base_2 const, int, int> 425 >(); 426 } 427 } 428