//===----------------------------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // UNSUPPORTED: c++98, c++03, c++11 // // template constexpr decltype(auto) apply(F &&, T &&) // Testing extended function types. The extented function types are those // named by INVOKE but that are not actual callable objects. These include // bullets 1-4 of invoke. #include #include #include #include // std::array is explicitly allowed to be initialized with A a = { init-list };. // Disable the missing braces warning for this reason. #include "disable_missing_braces_warning.h" int count = 0; struct A_int_0 { A_int_0() : obj1(0){} A_int_0(int x) : obj1(x) {} int mem1() { return ++count; } int mem2() const { return ++count; } int const obj1; }; struct A_int_1 { A_int_1() {} A_int_1(int) {} int mem1(int x) { return count += x; } int mem2(int x) const { return count += x; } }; struct A_int_2 { A_int_2() {} A_int_2(int) {} int mem1(int x, int y) { return count += (x + y); } int mem2(int x, int y) const { return count += (x + y); } }; template struct A_wrap { A_wrap() {} A_wrap(int x) : m_a(x) {} A & operator*() { return m_a; } A const & operator*() const { return m_a; } A m_a; }; typedef A_wrap A_wrap_0; typedef A_wrap A_wrap_1; typedef A_wrap A_wrap_2; template struct A_base : public A { A_base() : A() {} A_base(int x) : A(x) {} }; typedef A_base A_base_0; typedef A_base A_base_1; typedef A_base A_base_2; namespace ex = std::experimental; template < class Tuple, class ConstTuple , class TuplePtr, class ConstTuplePtr , class TupleWrap, class ConstTupleWrap , class TupleBase, class ConstTupleBase > void test_ext_int_0() { count = 0; typedef A_int_0 T; typedef A_wrap_0 Wrap; typedef A_base_0 Base; typedef int(T::*mem1_t)(); mem1_t mem1 = &T::mem1; typedef int(T::*mem2_t)() const; mem2_t mem2 = &T::mem2; typedef int const T::*obj1_t; obj1_t obj1 = &T::obj1; // member function w/ref { T a; Tuple t{a}; assert(1 == ex::apply(mem1, t)); assert(count == 1); } count = 0; // member function w/pointer { T a; TuplePtr t{&a}; assert(1 == ex::apply(mem1, t)); assert(count == 1); } count = 0; // member function w/base { Base a; TupleBase t{a}; assert(1 == ex::apply(mem1, t)); assert(count == 1); } count = 0; // member function w/wrap { Wrap a; TupleWrap t{a}; assert(1 == ex::apply(mem1, t)); assert(count == 1); } count = 0; // const member function w/ref { T const a; ConstTuple t{a}; assert(1 == ex::apply(mem2, t)); assert(count == 1); } count = 0; // const member function w/pointer { T const a; ConstTuplePtr t{&a}; assert(1 == ex::apply(mem2, t)); assert(count == 1); } count = 0; // const member function w/base { Base const a; ConstTupleBase t{a}; assert(1 == ex::apply(mem2, t)); assert(count == 1); } count = 0; // const member function w/wrapper { Wrap const a; ConstTupleWrap t{a}; assert(1 == ex::apply(mem2, t)); assert(1 == count); } // member object w/ref { T a{42}; Tuple t{a}; assert(42 == ex::apply(obj1, t)); } // member object w/pointer { T a{42}; TuplePtr t{&a}; assert(42 == ex::apply(obj1, t)); } // member object w/base { Base a{42}; TupleBase t{a}; assert(42 == ex::apply(obj1, t)); } // member object w/wrapper { Wrap a{42}; TupleWrap t{a}; assert(42 == ex::apply(obj1, t)); } } template < class Tuple, class ConstTuple , class TuplePtr, class ConstTuplePtr , class TupleWrap, class ConstTupleWrap , class TupleBase, class ConstTupleBase > void test_ext_int_1() { count = 0; typedef A_int_1 T; typedef A_wrap_1 Wrap; typedef A_base_1 Base; typedef int(T::*mem1_t)(int); mem1_t mem1 = &T::mem1; typedef int(T::*mem2_t)(int) const; mem2_t mem2 = &T::mem2; // member function w/ref { T a; Tuple t{a, 2}; assert(2 == ex::apply(mem1, t)); assert(count == 2); } count = 0; // member function w/pointer { T a; TuplePtr t{&a, 3}; assert(3 == ex::apply(mem1, t)); assert(count == 3); } count = 0; // member function w/base { Base a; TupleBase t{a, 4}; assert(4 == ex::apply(mem1, t)); assert(count == 4); } count = 0; // member function w/wrap { Wrap a; TupleWrap t{a, 5}; assert(5 == ex::apply(mem1, t)); assert(count == 5); } count = 0; // const member function w/ref { T const a; ConstTuple t{a, 6}; assert(6 == ex::apply(mem2, t)); assert(count == 6); } count = 0; // const member function w/pointer { T const a; ConstTuplePtr t{&a, 7}; assert(7 == ex::apply(mem2, t)); assert(count == 7); } count = 0; // const member function w/base { Base const a; ConstTupleBase t{a, 8}; assert(8 == ex::apply(mem2, t)); assert(count == 8); } count = 0; // const member function w/wrapper { Wrap const a; ConstTupleWrap t{a, 9}; assert(9 == ex::apply(mem2, t)); assert(9 == count); } } template < class Tuple, class ConstTuple , class TuplePtr, class ConstTuplePtr , class TupleWrap, class ConstTupleWrap , class TupleBase, class ConstTupleBase > void test_ext_int_2() { count = 0; typedef A_int_2 T; typedef A_wrap_2 Wrap; typedef A_base_2 Base; typedef int(T::*mem1_t)(int, int); mem1_t mem1 = &T::mem1; typedef int(T::*mem2_t)(int, int) const; mem2_t mem2 = &T::mem2; // member function w/ref { T a; Tuple t{a, 1, 1}; assert(2 == ex::apply(mem1, t)); assert(count == 2); } count = 0; // member function w/pointer { T a; TuplePtr t{&a, 1, 2}; assert(3 == ex::apply(mem1, t)); assert(count == 3); } count = 0; // member function w/base { Base a; TupleBase t{a, 2, 2}; assert(4 == ex::apply(mem1, t)); assert(count == 4); } count = 0; // member function w/wrap { Wrap a; TupleWrap t{a, 2, 3}; assert(5 == ex::apply(mem1, t)); assert(count == 5); } count = 0; // const member function w/ref { T const a; ConstTuple t{a, 3, 3}; assert(6 == ex::apply(mem2, t)); assert(count == 6); } count = 0; // const member function w/pointer { T const a; ConstTuplePtr t{&a, 3, 4}; assert(7 == ex::apply(mem2, t)); assert(count == 7); } count = 0; // const member function w/base { Base const a; ConstTupleBase t{a, 4, 4}; assert(8 == ex::apply(mem2, t)); assert(count == 8); } count = 0; // const member function w/wrapper { Wrap const a; ConstTupleWrap t{a, 4, 5}; assert(9 == ex::apply(mem2, t)); assert(9 == count); } } int main() { { test_ext_int_0< std::tuple, std::tuple , std::tuple, std::tuple , std::tuple, std::tuple , std::tuple, std::tuple >(); test_ext_int_0< std::tuple, std::tuple , std::tuple, std::tuple , std::tuple, std::tuple , std::tuple, std::tuple >(); test_ext_int_0< std::array, std::array , std::array, std::array , std::array, std::array , std::array, std::array >(); } { test_ext_int_1< std::tuple, std::tuple , std::tuple, std::tuple , std::tuple, std::tuple , std::tuple, std::tuple >(); test_ext_int_1< std::tuple, std::tuple , std::tuple, std::tuple , std::tuple, std::tuple , std::tuple, std::tuple >(); test_ext_int_1< std::pair, std::pair , std::pair, std::pair , std::pair, std::pair , std::pair, std::pair >(); test_ext_int_1< std::pair, std::pair , std::pair, std::pair , std::pair, std::pair , std::pair, std::pair >(); } { test_ext_int_2< std::tuple, std::tuple , std::tuple, std::tuple , std::tuple, std::tuple , std::tuple, std::tuple >(); test_ext_int_2< std::tuple, std::tuple , std::tuple, std::tuple , std::tuple, std::tuple , std::tuple, std::tuple >(); } }