blob: 56dc3c6aaa2522561b733bd12a1986ef39781da4 [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 with different ref/ptr/cv qualified argument types.
#include <experimental/tuple>
#include <array>
#include <utility>
#include <cassert>
namespace ex = std::experimental;
int call_with_value(int x, int y) { return (x + y); }
int call_with_ref(int & x, int & y) { return (x + y); }
int call_with_const_ref(int const & x, int const & y) { return (x + y); }
int call_with_rvalue_ref(int && x, int && y) { return (x + y); }
int call_with_pointer(int * x, int * y) { return (*x + *y); }
int call_with_const_pointer(int const* x, int const * y) { return (*x + *y); }
template <class Tuple>
void test_values()
{
{
Tuple t{1, 2};
assert(3 == ex::apply(call_with_value, t));
}
{
Tuple t{2, 2};
assert(4 == ex::apply(call_with_ref, t));
}
{
Tuple t{2, 3};
assert(5 == ex::apply(call_with_const_ref, t));
}
{
Tuple t{3, 3};
assert(6 == ex::apply(call_with_rvalue_ref, static_cast<Tuple &&>(t)));
}
{
Tuple const t{4, 4};
assert(8 == ex::apply(call_with_value, t));
}
{
Tuple const t{4, 5};
assert(9 == ex::apply(call_with_const_ref, t));
}
}
template <class Tuple>
void test_refs()
{
int x = 0;
int y = 0;
{
x = 1; y = 2;
Tuple t{x, y};
assert(3 == ex::apply(call_with_value, t));
}
{
x = 2; y = 2;
Tuple t{x, y};
assert(4 == ex::apply(call_with_ref, t));
}
{
x = 2; y = 3;
Tuple t{x, y};
assert(5 == ex::apply(call_with_const_ref, t));
}
{
x = 3; y = 3;
Tuple const t{x, y};
assert(6 == ex::apply(call_with_value, t));
}
{
x = 3; y = 4;
Tuple const t{x, y};
assert(7 == ex::apply(call_with_const_ref, t));
}
}
template <class Tuple>
void test_const_refs()
{
int x = 0;
int y = 0;
{
x = 1; y = 2;
Tuple t{x, y};
assert(3 == ex::apply(call_with_value, t));
}
{
x = 2; y = 3;
Tuple t{x, y};
assert(5 == ex::apply(call_with_const_ref, t));
}
{
x = 3; y = 3;
Tuple const t{x, y};
assert(6 == ex::apply(call_with_value, t));
}
{
x = 3; y = 4;
Tuple const t{x, y};
assert(7 == ex::apply(call_with_const_ref, t));
}
}
template <class Tuple>
void test_pointer()
{
int x = 0;
int y = 0;
{
x = 2; y = 2;
Tuple t{&x, &y};
assert(4 == ex::apply(call_with_pointer, t));
}
{
x = 2; y = 3;
Tuple t{&x, &y};
assert(5 == ex::apply(call_with_const_pointer, t));
}
{
x = 3; y = 4;
Tuple const t{&x, &y};
assert(7 == ex::apply(call_with_const_pointer, t));
}
}
template <class Tuple>
void test_const_pointer()
{
int x = 0;
int y = 0;
{
x = 2; y = 3;
Tuple t{&x, &y};
assert(5 == ex::apply(call_with_const_pointer, t));
}
{
x = 3; y = 4;
Tuple const t{&x, &y};
assert(7 == ex::apply(call_with_const_pointer, t));
}
}
int main()
{
test_values<std::tuple<int, int>>();
test_values<std::pair<int, int>>();
test_values<std::array<int, 2>>();
test_refs<std::tuple<int &, int &>>();
test_refs<std::pair<int &, int &>>();
test_const_refs<std::tuple<int const &, int const &>>();
test_const_refs<std::pair<int const &, int const &>>();
test_pointer<std::tuple<int *, int *>>();
test_pointer<std::pair<int *, int *>>();
test_pointer<std::array<int *, 2>>();
test_const_pointer<std::tuple<int const *, int const *>>();
test_const_pointer<std::pair<int const *, int const *>>();
test_const_pointer<std::array<int const *, 2>>();
}