blob: 5d3d564c26fbbab0bbe2852f195c0e72f059029d [file] [log] [blame]
//===----------------------------------------------------------------------===//
//
// 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
// <experimental/tuple>
// template <class F, class T> constexpr decltype(auto) apply(F &&, T &&)
// Test function types.
#include <experimental/tuple>
#include <array>
#include <utility>
#include <cassert>
namespace ex = std::experimental;
int count = 0;
void f_void_0() { ++count; }
void f_void_1(int i) { count += i; }
void f_void_2(int x, int y) { count += (x + y); }
void f_void_3(int x, int y, int z) { count += (x + y + z); }
int f_int_0() { return ++count; }
int f_int_1(int x) { return count += x; }
int f_int_2(int x, int y) { return count += (x + y); }
int f_int_3(int x, int y, int z) { return count += (x + y + z); }
struct A_void_0
{
A_void_0() {}
void operator()() { ++count; }
void operator()() const { ++count; ++count; }
};
struct A_void_1
{
A_void_1() {}
void operator()(int x) { count += x; }
void operator()(int x) const { count += x + 1; }
};
struct A_void_2
{
A_void_2() {}
void operator()(int x, int y) { count += (x + y); }
void operator()(int x, int y) const { count += (x + y) + 1; }
};
struct A_void_3
{
A_void_3() {}
void operator()(int x, int y, int z) { count += (x + y + z); }
void operator()(int x, int y, int z) const { count += (x + y + z) + 1; }
};
struct A_int_0
{
A_int_0() {}
int operator()() { return ++count; }
int operator()() const { ++count; return ++count; }
};
struct A_int_1
{
A_int_1() {}
int operator()(int x) { return count += x; }
int operator()(int x) const { return count += (x + 1); }
};
struct A_int_2
{
A_int_2() {}
int operator()(int x, int y) { return count += (x + y); }
int operator()(int x, int y) const { return count += (x + y + 1); }
};
struct A_int_3
{
A_int_3() {}
int operator()(int x, int y, int z) { return count += (x + y + z); }
int operator()(int x, int y, int z) const { return count += (x + y + z + 1); }
};
template <class Tuple>
void test_void_0()
{
count = 0;
// function
{
Tuple t{};
ex::apply(f_void_0, t);
assert(count == 1);
}
count = 0;
// function pointer
{
Tuple t{};
auto fp = &f_void_0;
ex::apply(fp, t);
assert(count == 1);
}
count = 0;
// functor
{
Tuple t{};
A_void_0 a;
ex::apply(a, t);
assert(count == 1);
}
count = 0;
// const functor
{
Tuple t{};
A_void_0 const a;
ex::apply(a, t);
assert(count == 2);
}
}
template <class Tuple>
void test_void_1()
{
count = 0;
// function
{
Tuple t{1};
ex::apply(f_void_1, t);
assert(count == 1);
}
count = 0;
// function pointer
{
Tuple t{2};
void (*fp)(int) = f_void_1;
ex::apply(fp, t);
assert(count == 2);
}
count = 0;
// functor
{
Tuple t{3};
A_void_1 fn;
ex::apply(fn, t);
assert(count == 3);
}
count = 0;
// const functor
{
Tuple t{4};
A_void_1 const a;
ex::apply(a, t);
assert(count == 5);
}
}
template <class Tuple>
void test_void_2()
{
count = 0;
// function
{
Tuple t{1, 2};
ex::apply(f_void_2, t);
assert(count == 3);
}
count = 0;
// function pointer
{
Tuple t{2, 3};
auto fp = &f_void_2;
ex::apply(fp, t);
assert(count == 5);
}
count = 0;
// functor
{
Tuple t{3, 4};
A_void_2 a;
ex::apply(a, t);
assert(count == 7);
}
count = 0;
// const functor
{
Tuple t{4, 5};
A_void_2 const a;
ex::apply(a, t);
assert(count == 10);
}
}
template <class Tuple>
void test_void_3()
{
count = 0;
// function
{
Tuple t{1, 2, 3};
ex::apply(f_void_3, t);
assert(count == 6);
}
count = 0;
// function pointer
{
Tuple t{2, 3, 4};
auto fp = &f_void_3;
ex::apply(fp, t);
assert(count == 9);
}
count = 0;
// functor
{
Tuple t{3, 4, 5};
A_void_3 a;
ex::apply(a, t);
assert(count == 12);
}
count = 0;
// const functor
{
Tuple t{4, 5, 6};
A_void_3 const a;
ex::apply(a, t);
assert(count == 16);
}
}
template <class Tuple>
void test_int_0()
{
count = 0;
// function
{
Tuple t{};
assert(1 == ex::apply(f_int_0, t));
assert(count == 1);
}
count = 0;
// function pointer
{
Tuple t{};
auto fp = &f_int_0;
assert(1 == ex::apply(fp, t));
assert(count == 1);
}
count = 0;
// functor
{
Tuple t{};
A_int_0 a;
assert(1 == ex::apply(a, t));
assert(count == 1);
}
count = 0;
// const functor
{
Tuple t{};
A_int_0 const a;
assert(2 == ex::apply(a, t));
assert(count == 2);
}
}
template <class Tuple>
void test_int_1()
{
count = 0;
// function
{
Tuple t{1};
assert(1 == ex::apply(f_int_1, t));
assert(count == 1);
}
count = 0;
// function pointer
{
Tuple t{2};
int (*fp)(int) = f_int_1;
assert(2 == ex::apply(fp, t));
assert(count == 2);
}
count = 0;
// functor
{
Tuple t{3};
A_int_1 fn;
assert(3 == ex::apply(fn, t));
assert(count == 3);
}
count = 0;
// const functor
{
Tuple t{4};
A_int_1 const a;
assert(5 == ex::apply(a, t));
assert(count == 5);
}
}
template <class Tuple>
void test_int_2()
{
count = 0;
// function
{
Tuple t{1, 2};
assert(3 == ex::apply(f_int_2, t));
assert(count == 3);
}
count = 0;
// function pointer
{
Tuple t{2, 3};
auto fp = &f_int_2;
assert(5 == ex::apply(fp, t));
assert(count == 5);
}
count = 0;
// functor
{
Tuple t{3, 4};
A_int_2 a;
assert(7 == ex::apply(a, t));
assert(count == 7);
}
count = 0;
// const functor
{
Tuple t{4, 5};
A_int_2 const a;
assert(10 == ex::apply(a, t));
assert(count == 10);
}
}
template <class Tuple>
void test_int_3()
{
count = 0;
// function
{
Tuple t{1, 2, 3};
assert(6 == ex::apply(f_int_3, t));
assert(count == 6);
}
count = 0;
// function pointer
{
Tuple t{2, 3, 4};
auto fp = &f_int_3;
assert(9 == ex::apply(fp, t));
assert(count == 9);
}
count = 0;
// functor
{
Tuple t{3, 4, 5};
A_int_3 a;
assert(12 == ex::apply(a, t));
assert(count == 12);
}
count = 0;
// const functor
{
Tuple t{4, 5, 6};
A_int_3 const a;
assert(16 == ex::apply(a, t));
assert(count == 16);
}
}
template <class Tuple>
void test_0()
{
test_void_0<Tuple>();
test_int_0<Tuple>();
}
template <class Tuple>
void test_1()
{
test_void_1<Tuple>();
test_int_1<Tuple>();
}
template <class Tuple>
void test_2()
{
test_void_2<Tuple>();
test_int_2<Tuple>();
}
template <class Tuple>
void test_3()
{
test_void_3<Tuple>();
test_int_3<Tuple>();
}
int main()
{
test_0<std::tuple<>>();
test_1<std::tuple<int>>();
test_1<std::array<int, 1>>();
test_2<std::tuple<int, int>>();
test_2<std::pair<int, int>>();
test_2<std::array<int, 2>>();
test_3<std::tuple<int, int, int>>();
test_3<std::array<int, 3>>();
}