Add constexpr to pair

Reviewed By: #libc, ldionne

Differential Revision: https://reviews.llvm.org/D80558
This commit is contained in:
Michael Schellenberger Costa 2020-09-02 21:20:33 +02:00
parent 5d1fe3f903
commit 737a4501e8
14 changed files with 466 additions and 365 deletions

View File

@ -184,6 +184,8 @@ Status
------------------------------------------------- -----------------
``__cpp_lib_constexpr_swap_algorithms`` *unimplemented*
------------------------------------------------- -----------------
``__cpp_lib_constexpr_utility `` ``201811L``
------------------------------------------------- -----------------
``__cpp_lib_destroying_delete`` ``201806L``
------------------------------------------------- -----------------
``__cpp_lib_endian`` ``201907L``

View File

@ -1393,7 +1393,7 @@ struct _LIBCPP_TEMPLATE_VIS uses_allocator<tuple<_Tp...>, _Alloc>
template <class _T1, class _T2>
template <class... _Args1, class... _Args2, size_t ..._I1, size_t ..._I2>
inline _LIBCPP_INLINE_VISIBILITY
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
pair<_T1, _T2>::pair(piecewise_construct_t,
tuple<_Args1...>& __first_args, tuple<_Args2...>& __second_args,
__tuple_indices<_I1...>, __tuple_indices<_I2...>)

View File

@ -499,7 +499,7 @@ struct _LIBCPP_TEMPLATE_VIS pair
second(_VSTD::get<1>(_VSTD::forward<_Tuple>(__p))) {}
template <class... _Args1, class... _Args2>
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
pair(piecewise_construct_t __pc,
tuple<_Args1...> __first_args, tuple<_Args2...> __second_args)
_NOEXCEPT_((is_nothrow_constructible<first_type, _Args1...>::value &&
@ -508,7 +508,7 @@ struct _LIBCPP_TEMPLATE_VIS pair
typename __make_tuple_indices<sizeof...(_Args1)>::type(),
typename __make_tuple_indices<sizeof...(_Args2) >::type()) {}
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
pair& operator=(typename conditional<
is_copy_assignable<first_type>::value &&
is_copy_assignable<second_type>::value,
@ -521,7 +521,7 @@ struct _LIBCPP_TEMPLATE_VIS pair
return *this;
}
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
pair& operator=(typename conditional<
is_move_assignable<first_type>::value &&
is_move_assignable<second_type>::value,
@ -537,7 +537,7 @@ struct _LIBCPP_TEMPLATE_VIS pair
template <class _Tuple, _EnableB<
_CheckTLC<_Tuple>::template __enable_assign<_Tuple>()
> = false>
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
pair& operator=(_Tuple&& __p) {
first = _VSTD::get<0>(_VSTD::forward<_Tuple>(__p));
second = _VSTD::get<1>(_VSTD::forward<_Tuple>(__p));
@ -545,7 +545,7 @@ struct _LIBCPP_TEMPLATE_VIS pair
}
#endif
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
void
swap(pair& __p) _NOEXCEPT_(__is_nothrow_swappable<first_type>::value &&
__is_nothrow_swappable<second_type>::value)
@ -558,10 +558,10 @@ private:
#ifndef _LIBCPP_CXX03_LANG
template <class... _Args1, class... _Args2, size_t... _I1, size_t... _I2>
_LIBCPP_INLINE_VISIBILITY
pair(piecewise_construct_t,
tuple<_Args1...>& __first_args, tuple<_Args2...>& __second_args,
__tuple_indices<_I1...>, __tuple_indices<_I2...>);
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
pair(piecewise_construct_t,
tuple<_Args1...>& __first_args, tuple<_Args2...>& __second_args,
__tuple_indices<_I1...>, __tuple_indices<_I2...>);
#endif
};
@ -619,7 +619,7 @@ operator<=(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y)
}
template <class _T1, class _T2>
inline _LIBCPP_INLINE_VISIBILITY
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
typename enable_if
<
__is_swappable<_T1>::value &&

View File

@ -42,6 +42,7 @@ __cpp_lib_concepts 201806L <concepts>
__cpp_lib_constexpr_misc 201811L <array> <functional> <iterator>
<string_view> <tuple> <utility>
__cpp_lib_constexpr_swap_algorithms 201806L <algorithm>
__cpp_lib_constexpr_utility 201811L <utility>
__cpp_lib_destroying_delete 201806L <new>
__cpp_lib_enable_shared_from_this 201603L <memory>
__cpp_lib_endian 201907L <bit>
@ -227,6 +228,7 @@ __cpp_lib_void_t 201411L <type_traits>
// # define __cpp_lib_concepts 201806L
// # define __cpp_lib_constexpr_misc 201811L
// # define __cpp_lib_constexpr_swap_algorithms 201806L
# define __cpp_lib_constexpr_utility 201811L
# if _LIBCPP_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L
# define __cpp_lib_destroying_delete 201806L
# endif

View File

@ -13,13 +13,14 @@
// Test the feature test macros defined by <utility>
/* Constant Value
__cpp_lib_as_const 201510L [C++17]
__cpp_lib_constexpr_misc 201811L [C++2a]
__cpp_lib_exchange_function 201304L [C++14]
__cpp_lib_integer_sequence 201304L [C++14]
__cpp_lib_to_chars 201611L [C++17]
__cpp_lib_tuples_by_type 201304L [C++14]
/* Constant Value
__cpp_lib_as_const 201510L [C++17]
__cpp_lib_constexpr_misc 201811L [C++2a]
__cpp_lib_constexpr_utility 201811L [C++2a]
__cpp_lib_exchange_function 201304L [C++14]
__cpp_lib_integer_sequence 201304L [C++14]
__cpp_lib_to_chars 201611L [C++17]
__cpp_lib_tuples_by_type 201304L [C++14]
*/
#include <utility>
@ -35,6 +36,10 @@
# error "__cpp_lib_constexpr_misc should not be defined before c++2a"
# endif
# ifdef __cpp_lib_constexpr_utility
# error "__cpp_lib_constexpr_utility should not be defined before c++2a"
# endif
# ifdef __cpp_lib_exchange_function
# error "__cpp_lib_exchange_function should not be defined before c++14"
# endif
@ -61,6 +66,10 @@
# error "__cpp_lib_constexpr_misc should not be defined before c++2a"
# endif
# ifdef __cpp_lib_constexpr_utility
# error "__cpp_lib_constexpr_utility should not be defined before c++2a"
# endif
# ifndef __cpp_lib_exchange_function
# error "__cpp_lib_exchange_function should be defined in c++14"
# endif
@ -99,6 +108,10 @@
# error "__cpp_lib_constexpr_misc should not be defined before c++2a"
# endif
# ifdef __cpp_lib_constexpr_utility
# error "__cpp_lib_constexpr_utility should not be defined before c++2a"
# endif
# ifndef __cpp_lib_exchange_function
# error "__cpp_lib_exchange_function should be defined in c++17"
# endif
@ -155,6 +168,13 @@
# endif
# endif
# ifndef __cpp_lib_constexpr_utility
# error "__cpp_lib_constexpr_utility should be defined in c++2a"
# endif
# if __cpp_lib_constexpr_utility != 201811L
# error "__cpp_lib_constexpr_utility should have the value 201811L in c++2a"
# endif
# ifndef __cpp_lib_exchange_function
# error "__cpp_lib_exchange_function should be defined in c++2a"
# endif

View File

@ -36,6 +36,7 @@
__cpp_lib_concepts 201806L [C++2a]
__cpp_lib_constexpr_misc 201811L [C++2a]
__cpp_lib_constexpr_swap_algorithms 201806L [C++2a]
__cpp_lib_constexpr_utility 201811L [C++2a]
__cpp_lib_destroying_delete 201806L [C++2a]
__cpp_lib_enable_shared_from_this 201603L [C++17]
__cpp_lib_endian 201907L [C++2a]
@ -194,6 +195,10 @@
# error "__cpp_lib_constexpr_swap_algorithms should not be defined before c++2a"
# endif
# ifdef __cpp_lib_constexpr_utility
# error "__cpp_lib_constexpr_utility should not be defined before c++2a"
# endif
# ifdef __cpp_lib_destroying_delete
# error "__cpp_lib_destroying_delete should not be defined before c++2a"
# endif
@ -550,6 +555,10 @@
# error "__cpp_lib_constexpr_swap_algorithms should not be defined before c++2a"
# endif
# ifdef __cpp_lib_constexpr_utility
# error "__cpp_lib_constexpr_utility should not be defined before c++2a"
# endif
# ifdef __cpp_lib_destroying_delete
# error "__cpp_lib_destroying_delete should not be defined before c++2a"
# endif
@ -1020,6 +1029,10 @@
# error "__cpp_lib_constexpr_swap_algorithms should not be defined before c++2a"
# endif
# ifdef __cpp_lib_constexpr_utility
# error "__cpp_lib_constexpr_utility should not be defined before c++2a"
# endif
# ifdef __cpp_lib_destroying_delete
# error "__cpp_lib_destroying_delete should not be defined before c++2a"
# endif
@ -1721,6 +1734,13 @@
# endif
# endif
# ifndef __cpp_lib_constexpr_utility
# error "__cpp_lib_constexpr_utility should be defined in c++2a"
# endif
# if __cpp_lib_constexpr_utility != 201811L
# error "__cpp_lib_constexpr_utility should have the value 201811L in c++2a"
# endif
# if TEST_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L
# ifndef __cpp_lib_destroying_delete
# error "__cpp_lib_destroying_delete should be defined in c++2a"

View File

@ -20,33 +20,51 @@
#include "archetypes.h"
#endif
int main(int, char**)
{
{
typedef std::pair<int, short> P1;
typedef std::pair<double, long> P2;
P1 p1(3, static_cast<short>(4));
P2 p2;
p2 = p1;
assert(p2.first == 3);
assert(p2.second == 4);
}
#if TEST_STD_VER >= 11
{
using C = TestTypes::TestType;
using P = std::pair<int, C>;
using T = std::pair<long, C>;
const T t(42, -42);
P p(101, 101);
C::reset_constructors();
p = t;
assert(C::constructed == 0);
assert(C::assigned == 1);
assert(C::copy_assigned == 1);
assert(C::move_assigned == 0);
assert(p.first == 42);
assert(p.second.value == -42);
}
TEST_CONSTEXPR_CXX20 bool test() {
{
typedef std::pair<int, short> P1;
typedef std::pair<double, long> P2;
P1 p1(3, static_cast<short>(4));
P2 p2;
p2 = p1;
assert(p2.first == 3);
assert(p2.second == 4);
}
#if TEST_STD_VER >= 20
{
using C = ConstexprTestTypes::TestType;
using P = std::pair<int, C>;
using T = std::pair<long, C>;
const T t(42, -42);
P p(101, 101);
p = t;
assert(p.first == 42);
assert(p.second.value == -42);
}
#elif TEST_STD_VER >= 11
{
using C = TestTypes::TestType;
using P = std::pair<int, C>;
using T = std::pair<long, C>;
const T t(42, -42);
P p(101, 101);
C::reset_constructors();
p = t;
assert(C::constructed == 0);
assert(C::assigned == 1);
assert(C::copy_assigned == 1);
assert(C::move_assigned == 0);
assert(p.first == 42);
assert(p.second.value == -42);
}
#endif
return true;
}
int main(int, char**) {
test();
#if TEST_STD_VER >= 20
static_assert(test());
#endif
return 0;

View File

@ -19,85 +19,81 @@
#include <cassert>
#include "test_macros.h"
struct NonAssignable {
NonAssignable& operator=(NonAssignable const&) = delete;
NonAssignable& operator=(NonAssignable&&) = delete;
};
struct CopyAssignable {
CopyAssignable() = default;
CopyAssignable(CopyAssignable const&) = default;
CopyAssignable& operator=(CopyAssignable const&) = default;
CopyAssignable& operator=(CopyAssignable&&) = delete;
};
struct MoveAssignable {
MoveAssignable() = default;
MoveAssignable& operator=(MoveAssignable const&) = delete;
MoveAssignable& operator=(MoveAssignable&&) = default;
};
#include "archetypes.h"
struct CountAssign {
static int copied;
static int moved;
static void reset() { copied = moved = 0; }
CountAssign() = default;
CountAssign& operator=(CountAssign const&) { ++copied; return *this; }
CountAssign& operator=(CountAssign&&) { ++moved; return *this; }
int copied = 0;
int moved = 0;
TEST_CONSTEXPR_CXX20 CountAssign() = default;
TEST_CONSTEXPR_CXX20 CountAssign& operator=(CountAssign const&) {
++copied;
return *this;
}
TEST_CONSTEXPR_CXX20 CountAssign& operator=(CountAssign&&) {
++moved;
return *this;
}
};
int CountAssign::copied = 0;
int CountAssign::moved = 0;
struct Incomplete;
extern Incomplete inc_obj;
int main(int, char**)
{
{
typedef std::pair<CopyAssignable, int> P;
const P p1(CopyAssignable(), short{4});
P p2;
p2 = p1;
assert(p2.second == 4);
}
{
using P = std::pair<int&, int&&>;
int x = 42;
int y = 101;
int x2 = -1;
int y2 = 300;
P p1(x, std::move(y));
P p2(x2, std::move(y2));
p1 = p2;
assert(p1.first == x2);
assert(p1.second == y2);
}
{
using P = std::pair<int, NonAssignable>;
static_assert(!std::is_copy_assignable<P>::value, "");
}
{
CountAssign::reset();
using P = std::pair<CountAssign, CopyAssignable>;
static_assert(std::is_copy_assignable<P>::value, "");
P p;
P p2;
p = p2;
assert(CountAssign::copied == 1);
assert(CountAssign::moved == 0);
}
{
using P = std::pair<int, MoveAssignable>;
static_assert(!std::is_copy_assignable<P>::value, "");
}
{
using P = std::pair<int, Incomplete&>;
static_assert(!std::is_copy_assignable<P>::value, "");
P p(42, inc_obj);
assert(&p.second == &inc_obj);
}
TEST_CONSTEXPR_CXX20 bool test() {
{
typedef std::pair<ConstexprTestTypes::CopyOnly, int> P;
const P p1(ConstexprTestTypes::CopyOnly(), short{4});
P p2;
p2 = p1;
assert(p2.second == 4);
}
{
using P = std::pair<int&, int&&>;
int x = 42;
int y = 101;
int x2 = -1;
int y2 = 300;
P p1(x, std::move(y));
P p2(x2, std::move(y2));
p1 = p2;
assert(p1.first == x2);
assert(p1.second == y2);
}
{
using P = std::pair<int, ConstexprTestTypes::NonCopyable>;
static_assert(!std::is_copy_assignable<P>::value, "");
}
{
using P = std::pair<CountAssign, ConstexprTestTypes::Copyable>;
static_assert(std::is_copy_assignable<P>::value, "");
P p;
P p2;
p = p2;
assert(p.first.copied == 1);
assert(p.first.moved == 0);
assert(p2.first.copied == 0);
assert(p2.first.moved == 0);
}
{
using P = std::pair<int, ConstexprTestTypes::MoveAssignOnly>;
static_assert(!std::is_copy_assignable<P>::value, "");
}
{
using P = std::pair<int, Incomplete&>;
static_assert(!std::is_copy_assignable<P>::value, "");
P p(42, inc_obj);
assert(&p.second == &inc_obj);
}
return 0;
return true;
}
int main(int, char**) {
test();
#if TEST_STD_VER >= 20
static_assert(test());
#endif
return 0;
}
struct Incomplete {};

View File

@ -19,81 +19,78 @@
#include <cassert>
#include "test_macros.h"
struct NonAssignable {
NonAssignable& operator=(NonAssignable const&) = delete;
NonAssignable& operator=(NonAssignable&&) = delete;
};
struct CopyAssignable {
CopyAssignable() = default;
CopyAssignable& operator=(CopyAssignable const&) = default;
CopyAssignable& operator=(CopyAssignable&&) = delete;
};
struct MoveAssignable {
MoveAssignable() = default;
MoveAssignable& operator=(MoveAssignable const&) = delete;
MoveAssignable& operator=(MoveAssignable&&) = default;
};
#include "archetypes.h"
struct CountAssign {
static int copied;
static int moved;
static void reset() { copied = moved = 0; }
CountAssign() = default;
CountAssign& operator=(CountAssign const&) { ++copied; return *this; }
CountAssign& operator=(CountAssign&&) { ++moved; return *this; }
int copied = 0;
int moved = 0;
TEST_CONSTEXPR_CXX20 CountAssign() = default;
TEST_CONSTEXPR_CXX20 CountAssign& operator=(CountAssign const&) {
++copied;
return *this;
}
TEST_CONSTEXPR_CXX20 CountAssign& operator=(CountAssign&&) {
++moved;
return *this;
}
};
int CountAssign::copied = 0;
int CountAssign::moved = 0;
int main(int, char**)
{
{
typedef std::pair<std::unique_ptr<int>, int> P;
P p1(std::unique_ptr<int>(new int(3)), 4);
P p2;
p2 = std::move(p1);
assert(*p2.first == 3);
assert(p2.second == 4);
}
{
using P = std::pair<int&, int&&>;
int x = 42;
int y = 101;
int x2 = -1;
int y2 = 300;
P p1(x, std::move(y));
P p2(x2, std::move(y2));
p1 = std::move(p2);
assert(p1.first == x2);
assert(p1.second == y2);
}
{
using P = std::pair<int, NonAssignable>;
static_assert(!std::is_move_assignable<P>::value, "");
}
{
// The move decays to the copy constructor
CountAssign::reset();
using P = std::pair<CountAssign, CopyAssignable>;
static_assert(std::is_move_assignable<P>::value, "");
P p;
P p2;
p = std::move(p2);
assert(CountAssign::moved == 0);
assert(CountAssign::copied == 1);
}
{
CountAssign::reset();
using P = std::pair<CountAssign, MoveAssignable>;
static_assert(std::is_move_assignable<P>::value, "");
P p;
P p2;
p = std::move(p2);
assert(CountAssign::moved == 1);
assert(CountAssign::copied == 0);
}
TEST_CONSTEXPR_CXX20 bool test() {
{
typedef std::pair<ConstexprTestTypes::MoveOnly, int> P;
P p1(3, 4);
P p2;
p2 = std::move(p1);
assert(p2.first.value == 3);
assert(p2.second == 4);
}
{
using P = std::pair<int&, int&&>;
int x = 42;
int y = 101;
int x2 = -1;
int y2 = 300;
P p1(x, std::move(y));
P p2(x2, std::move(y2));
p1 = std::move(p2);
assert(p1.first == x2);
assert(p1.second == y2);
}
{
using P = std::pair<int, ConstexprTestTypes::DefaultOnly>;
static_assert(!std::is_move_assignable<P>::value, "");
}
{
// The move decays to the copy constructor
using P = std::pair<CountAssign, ConstexprTestTypes::CopyOnly>;
static_assert(std::is_move_assignable<P>::value, "");
P p;
P p2;
p = std::move(p2);
assert(p.first.moved == 0);
assert(p.first.copied == 1);
assert(p2.first.moved == 0);
assert(p2.first.copied == 0);
}
{
using P = std::pair<CountAssign, ConstexprTestTypes::MoveOnly>;
static_assert(std::is_move_assignable<P>::value, "");
P p;
P p2;
p = std::move(p2);
assert(p.first.moved == 1);
assert(p.first.copied == 0);
assert(p2.first.moved == 0);
assert(p2.first.copied == 0);
}
return true;
}
int main(int, char**) {
test();
#if TEST_STD_VER >= 20
static_assert(test());
#endif
return 0;
}

View File

@ -17,46 +17,58 @@
#include <utility>
#include <memory>
#include <cassert>
#include <archetypes.h>
#include "test_macros.h"
#include "archetypes.h"
struct Base
{
virtual ~Base() {}
struct Derived : ConstexprTestTypes::MoveOnly {
Derived() = default;
TEST_CONSTEXPR_CXX20 Derived(ConstexprTestTypes::MoveOnly&&){};
};
struct CountAssign {
int copied = 0;
int moved = 0;
TEST_CONSTEXPR_CXX20 CountAssign() = default;
TEST_CONSTEXPR_CXX20 CountAssign(const int){};
TEST_CONSTEXPR_CXX20 CountAssign& operator=(CountAssign const&) {
++copied;
return *this;
}
TEST_CONSTEXPR_CXX20 CountAssign& operator=(CountAssign&&) {
++moved;
return *this;
}
};
struct Derived
: public Base
{
};
TEST_CONSTEXPR_CXX20 bool test() {
{
typedef std::pair<Derived, short> P1;
typedef std::pair<ConstexprTestTypes::MoveOnly, long> P2;
P1 p1(Derived(), static_cast<short>(4));
P2 p2;
p2 = std::move(p1);
assert(p2.second == 4);
}
{
using P = std::pair<int, CountAssign>;
using T = std::pair<long, CountAssign>;
T t(42, -42);
P p(101, 101);
p = std::move(t);
assert(p.first == 42);
assert(p.second.moved == 1);
assert(p.second.copied == 0);
assert(t.second.moved == 0);
assert(t.second.copied == 0);
}
return true;
}
int main(int, char**)
{
{
typedef std::pair<std::unique_ptr<Derived>, short> P1;
typedef std::pair<std::unique_ptr<Base>, long> P2;
P1 p1(std::unique_ptr<Derived>(), static_cast<short>(4));
P2 p2;
p2 = std::move(p1);
assert(p2.first == nullptr);
assert(p2.second == 4);
}
{
using C = TestTypes::TestType;
using P = std::pair<int, C>;
using T = std::pair<long, C>;
T t(42, -42);
P p(101, 101);
C::reset_constructors();
p = std::move(t);
assert(C::constructed == 0);
assert(C::assigned == 1);
assert(C::copy_assigned == 0);
assert(C::move_assigned == 1);
assert(p.first == 42);
assert(p.second.value == -42);
}
int main(int, char**) {
test();
#if TEST_STD_VER >= 20
static_assert(test());
#endif
return 0;
}

View File

@ -23,18 +23,16 @@
#include "test_macros.h"
using namespace ImplicitTypes; // Get implicitly archetypes
template <class T1, class U1,
bool CanCopy = true, bool CanConvert = CanCopy>
void test_pair_const()
{
using P1 = std::pair<T1, int>;
using P2 = std::pair<int, T1>;
using UP1 = std::pair<U1, int> const&;
using UP2 = std::pair<int, U1> const&;
static_assert(std::is_constructible<P1, UP1>::value == CanCopy, "");
static_assert(test_convertible<P1, UP1>() == CanConvert, "");
static_assert(std::is_constructible<P2, UP2>::value == CanCopy, "");
static_assert(test_convertible<P2, UP2>() == CanConvert, "");
template <class T1, class U1, bool CanCopy = true, bool CanConvert = CanCopy>
TEST_CONSTEXPR_CXX20 void test_pair_const() {
using P1 = std::pair<T1, int>;
using P2 = std::pair<int, T1>;
using UP1 = std::pair<U1, int> const&;
using UP2 = std::pair<int, U1> const&;
static_assert(std::is_constructible<P1, UP1>::value == CanCopy, "");
static_assert(test_convertible<P1, UP1>() == CanConvert, "");
static_assert(std::is_constructible<P2, UP2>::value == CanCopy, "");
static_assert(test_convertible<P2, UP2>() == CanConvert, "");
}
template <class T, class U>
@ -55,104 +53,115 @@ struct ImplicitT {
int value;
};
int main(int, char**)
{
{
typedef std::pair<int, int> P1;
typedef std::pair<double, long> P2;
const P1 p1(3, 4);
const P2 p2 = p1;
assert(p2.first == 3);
assert(p2.second == 4);
}
{
// We allow derived types to use this constructor
using P1 = DPair<long, long>;
using P2 = std::pair<int, int>;
P1 p1(42, 101);
P2 p2(p1);
assert(p2.first == 42);
assert(p2.second == 101);
}
{
test_pair_const<AllCtors, AllCtors>(); // copy construction
test_pair_const<AllCtors, AllCtors&>();
test_pair_const<AllCtors, AllCtors&&>();
test_pair_const<AllCtors, const AllCtors&>();
test_pair_const<AllCtors, const AllCtors&&>();
TEST_CONSTEXPR_CXX20 bool test() {
{
typedef std::pair<int, int> P1;
typedef std::pair<double, long> P2;
const P1 p1(3, 4);
const P2 p2 = p1;
assert(p2.first == 3);
assert(p2.second == 4);
}
{
// We allow derived types to use this constructor
using P1 = DPair<long, long>;
using P2 = std::pair<int, int>;
P1 p1(42, 101);
P2 p2(p1);
assert(p2.first == 42);
assert(p2.second == 101);
}
{
test_pair_const<AllCtors, AllCtors>(); // copy construction
test_pair_const<AllCtors, AllCtors&>();
test_pair_const<AllCtors, AllCtors&&>();
test_pair_const<AllCtors, const AllCtors&>();
test_pair_const<AllCtors, const AllCtors&&>();
test_pair_const<ExplicitTypes::AllCtors, ExplicitTypes::AllCtors>(); // copy construction
test_pair_const<ExplicitTypes::AllCtors, ExplicitTypes::AllCtors&, true, false>();
test_pair_const<ExplicitTypes::AllCtors, ExplicitTypes::AllCtors&&, true, false>();
test_pair_const<ExplicitTypes::AllCtors, const ExplicitTypes::AllCtors&, true, false>();
test_pair_const<ExplicitTypes::AllCtors, const ExplicitTypes::AllCtors&&, true, false>();
test_pair_const<ExplicitTypes::AllCtors,
ExplicitTypes::AllCtors>(); // copy construction
test_pair_const<ExplicitTypes::AllCtors, ExplicitTypes::AllCtors&, true,
false>();
test_pair_const<ExplicitTypes::AllCtors, ExplicitTypes::AllCtors&&, true,
false>();
test_pair_const<ExplicitTypes::AllCtors, const ExplicitTypes::AllCtors&,
true, false>();
test_pair_const<ExplicitTypes::AllCtors, const ExplicitTypes::AllCtors&&,
true, false>();
test_pair_const<MoveOnly, MoveOnly, false>(); // copy construction
test_pair_const<MoveOnly, MoveOnly&, false>();
test_pair_const<MoveOnly, MoveOnly&&, false>();
test_pair_const<MoveOnly, MoveOnly, false>(); // copy construction
test_pair_const<MoveOnly, MoveOnly&, false>();
test_pair_const<MoveOnly, MoveOnly&&, false>();
test_pair_const<ExplicitTypes::MoveOnly, ExplicitTypes::MoveOnly, false>(); // copy construction
test_pair_const<ExplicitTypes::MoveOnly, ExplicitTypes::MoveOnly&, false>();
test_pair_const<ExplicitTypes::MoveOnly, ExplicitTypes::MoveOnly&&, false>();
test_pair_const<ExplicitTypes::MoveOnly, ExplicitTypes::MoveOnly,
false>(); // copy construction
test_pair_const<ExplicitTypes::MoveOnly, ExplicitTypes::MoveOnly&, false>();
test_pair_const<ExplicitTypes::MoveOnly, ExplicitTypes::MoveOnly&&,
false>();
test_pair_const<CopyOnly, CopyOnly>();
test_pair_const<CopyOnly, CopyOnly&>();
test_pair_const<CopyOnly, CopyOnly&&>();
test_pair_const<CopyOnly, CopyOnly>();
test_pair_const<CopyOnly, CopyOnly&>();
test_pair_const<CopyOnly, CopyOnly&&>();
test_pair_const<ExplicitTypes::CopyOnly, ExplicitTypes::CopyOnly>();
test_pair_const<ExplicitTypes::CopyOnly, ExplicitTypes::CopyOnly&, true, false>();
test_pair_const<ExplicitTypes::CopyOnly, ExplicitTypes::CopyOnly&&, true, false>();
test_pair_const<ExplicitTypes::CopyOnly, ExplicitTypes::CopyOnly>();
test_pair_const<ExplicitTypes::CopyOnly, ExplicitTypes::CopyOnly&, true,
false>();
test_pair_const<ExplicitTypes::CopyOnly, ExplicitTypes::CopyOnly&&, true,
false>();
test_pair_const<NonCopyable, NonCopyable, false>();
test_pair_const<NonCopyable, NonCopyable&, false>();
test_pair_const<NonCopyable, NonCopyable&&, false>();
test_pair_const<NonCopyable, const NonCopyable&, false>();
test_pair_const<NonCopyable, const NonCopyable&&, false>();
}
test_pair_const<NonCopyable, NonCopyable, false>();
test_pair_const<NonCopyable, NonCopyable&, false>();
test_pair_const<NonCopyable, NonCopyable&&, false>();
test_pair_const<NonCopyable, const NonCopyable&, false>();
test_pair_const<NonCopyable, const NonCopyable&&, false>();
}
{ // Test construction of references
test_pair_const<NonCopyable&, NonCopyable&>();
test_pair_const<NonCopyable&, NonCopyable&&>();
test_pair_const<NonCopyable&, NonCopyable const&, false>();
test_pair_const<NonCopyable const&, NonCopyable&&>();
test_pair_const<NonCopyable&&, NonCopyable&&, false>();
{ // Test construction of references
test_pair_const<NonCopyable&, NonCopyable&>();
test_pair_const<NonCopyable&, NonCopyable&&>();
test_pair_const<NonCopyable&, NonCopyable const&, false>();
test_pair_const<NonCopyable const&, NonCopyable&&>();
test_pair_const<NonCopyable&&, NonCopyable&&, false>();
test_pair_const<ConvertingType&, int, false>();
test_pair_const<ExplicitTypes::ConvertingType&, int, false>();
// Unfortunately the below conversions are allowed and create dangling
// references.
//test_pair_const<ConvertingType&&, int>();
//test_pair_const<ConvertingType const&, int>();
//test_pair_const<ConvertingType const&&, int>();
// But these are not because the converting constructor is explicit.
test_pair_const<ExplicitTypes::ConvertingType&&, int, false>();
test_pair_const<ExplicitTypes::ConvertingType const&, int, false>();
test_pair_const<ExplicitTypes::ConvertingType const&&, int, false>();
test_pair_const<ConvertingType&, int, false>();
test_pair_const<ExplicitTypes::ConvertingType&, int, false>();
// Unfortunately the below conversions are allowed and create dangling
// references.
//test_pair_const<ConvertingType&&, int>();
//test_pair_const<ConvertingType const&, int>();
//test_pair_const<ConvertingType const&&, int>();
// But these are not because the converting constructor is explicit.
test_pair_const<ExplicitTypes::ConvertingType&&, int, false>();
test_pair_const<ExplicitTypes::ConvertingType const&, int, false>();
test_pair_const<ExplicitTypes::ConvertingType const&&, int, false>();
}
{
test_pair_const<AllCtors, int, false>();
test_pair_const<ExplicitTypes::AllCtors, int, false>();
test_pair_const<ConvertingType, int>();
test_pair_const<ExplicitTypes::ConvertingType, int, true, false>();
}
{
test_pair_const<AllCtors, int, false>();
test_pair_const<ExplicitTypes::AllCtors, int, false>();
test_pair_const<ConvertingType, int>();
test_pair_const<ExplicitTypes::ConvertingType, int, true, false>();
test_pair_const<ConvertingType, int>();
test_pair_const<ConvertingType, ConvertingType>();
test_pair_const<ConvertingType, ConvertingType const&>();
test_pair_const<ConvertingType, ConvertingType&>();
test_pair_const<ConvertingType, ConvertingType&&>();
test_pair_const<ConvertingType, int>();
test_pair_const<ConvertingType, ConvertingType>();
test_pair_const<ConvertingType, ConvertingType const&>();
test_pair_const<ConvertingType, ConvertingType&>();
test_pair_const<ConvertingType, ConvertingType&&>();
test_pair_const<ExplicitTypes::ConvertingType, int, true, false>();
test_pair_const<ExplicitTypes::ConvertingType, int&, true, false>();
test_pair_const<ExplicitTypes::ConvertingType, const int&, true, false>();
test_pair_const<ExplicitTypes::ConvertingType, int&&, true, false>();
test_pair_const<ExplicitTypes::ConvertingType, const int&&, true, false>();
test_pair_const<ExplicitTypes::ConvertingType, int, true, false>();
test_pair_const<ExplicitTypes::ConvertingType, int&, true, false>();
test_pair_const<ExplicitTypes::ConvertingType, const int&, true, false>();
test_pair_const<ExplicitTypes::ConvertingType, int&&, true, false>();
test_pair_const<ExplicitTypes::ConvertingType, const int&&, true, false>();
test_pair_const<ExplicitTypes::ConvertingType, ExplicitTypes::ConvertingType>();
test_pair_const<ExplicitTypes::ConvertingType, ExplicitTypes::ConvertingType const&, true, false>();
test_pair_const<ExplicitTypes::ConvertingType, ExplicitTypes::ConvertingType&, true, false>();
test_pair_const<ExplicitTypes::ConvertingType, ExplicitTypes::ConvertingType&&, true, false>();
}
test_pair_const<ExplicitTypes::ConvertingType,
ExplicitTypes::ConvertingType>();
test_pair_const<ExplicitTypes::ConvertingType,
ExplicitTypes::ConvertingType const&, true, false>();
test_pair_const<ExplicitTypes::ConvertingType,
ExplicitTypes::ConvertingType&, true, false>();
test_pair_const<ExplicitTypes::ConvertingType,
ExplicitTypes::ConvertingType&&, true, false>();
}
#if TEST_STD_VER > 11
{
typedef std::pair<int, int> P1;
@ -171,14 +180,22 @@ int main(int, char**)
static_assert(p2.second.value == 101, "");
}
{
using P1 = std::pair<int, int>;
using P2 = std::pair<ImplicitT, ImplicitT>;
constexpr P1 p1(42, 101);
constexpr P2 p2 = p1;
static_assert(p2.first.value == 42, "");
static_assert(p2.second.value == 101, "");
using P1 = std::pair<int, int>;
using P2 = std::pair<ImplicitT, ImplicitT>;
constexpr P1 p1(42, 101);
constexpr P2 p2 = p1;
static_assert(p2.first.value == 42, "");
static_assert(p2.second.value == 101, "");
}
#endif
return true;
}
int main(int, char**) {
test();
#if TEST_STD_VER >= 20
static_assert(test());
#endif
return 0;
}

View File

@ -22,18 +22,24 @@
#include "test_macros.h"
TEST_CONSTEXPR_CXX20 bool test() {
{
typedef std::pair<int, int*> P1;
typedef std::pair<int*, int> P2;
typedef std::pair<P1, P2> P3;
P3 p3(std::piecewise_construct, std::tuple<int, int*>(3, nullptr),
std::tuple<int*, int>(nullptr, 4));
assert(p3.first == P1(3, nullptr));
assert(p3.second == P2(nullptr, 4));
}
return true;
}
int main(int, char**)
{
{
typedef std::pair<int, int*> P1;
typedef std::pair<int*, int> P2;
typedef std::pair<P1, P2> P3;
P3 p3(std::piecewise_construct, std::tuple<int, int*>(3, nullptr),
std::tuple<int*, int>(nullptr, 4));
assert(p3.first == P1(3, nullptr));
assert(p3.second == P2(nullptr, 4));
}
int main(int, char**) {
test();
#if TEST_STD_VER >= 20
static_assert(test());
#endif
return 0;
}

View File

@ -19,35 +19,40 @@
struct S {
int i;
S() : i(0) {}
S(int j) : i(j) {}
S * operator& () { assert(false); return this; }
S const * operator& () const { assert(false); return this; }
bool operator==(int x) const { return i == x; }
};
TEST_CONSTEXPR_CXX20 S() : i(0) {}
TEST_CONSTEXPR_CXX20 S(int j) : i(j) {}
TEST_CONSTEXPR_CXX20 bool operator==(int x) const { return i == x; }
};
int main(int, char**)
{
{
typedef std::pair<int, short> P1;
P1 p1(3, static_cast<short>(4));
P1 p2(5, static_cast<short>(6));
p1.swap(p2);
assert(p1.first == 5);
assert(p1.second == 6);
assert(p2.first == 3);
assert(p2.second == 4);
}
{
typedef std::pair<int, S> P1;
P1 p1(3, S(4));
P1 p2(5, S(6));
p1.swap(p2);
assert(p1.first == 5);
assert(p1.second == 6);
assert(p2.first == 3);
assert(p2.second == 4);
}
TEST_CONSTEXPR_CXX20 bool test() {
{
typedef std::pair<int, short> P1;
P1 p1(3, static_cast<short>(4));
P1 p2(5, static_cast<short>(6));
p1.swap(p2);
assert(p1.first == 5);
assert(p1.second == 6);
assert(p2.first == 3);
assert(p2.second == 4);
}
{
typedef std::pair<int, S> P1;
P1 p1(3, S(4));
P1 p2(5, S(6));
p1.swap(p2);
assert(p1.first == 5);
assert(p1.second == 6);
assert(p2.first == 3);
assert(p2.second == 4);
}
return true;
}
int main(int, char**) {
test();
#if TEST_STD_VER >= 20
static_assert(test());
#endif
return 0;
}

View File

@ -607,6 +607,12 @@ feature_test_macros = sorted([ add_version_header(x) for x in [
"depends": "defined(__cpp_concepts) && __cpp_concepts >= 201811L",
"internal_depends": "defined(__cpp_concepts) && __cpp_concepts >= 201811L",
},
{"name": "__cpp_lib_constexpr_utility ",
"values": {
"c++2a": int(201811),
},
"headers": ["utility"],
},
]], key=lambda tc: tc["name"])
def get_std_dialects():