1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
|
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// <utility>
// template <class T1, class T2> struct pair
// Test the SFINAE required by LWG Issue #2367.
// is_default_constructible<pair>
// UNSUPPORTED: c++03
#include <utility>
#include <type_traits>
#include <cassert>
#include "test_macros.h"
#if TEST_STD_VER > 11
#define CONSTEXPR_CXX14 constexpr
#define STATIC_ASSERT_CXX14(Pred) static_assert(Pred, "")
#else
#define CONSTEXPR_CXX14
#define STATIC_ASSERT_CXX14(Pred) assert(Pred)
#endif
struct DeletedDefault {
// A class with a deleted default constructor. Used to test the SFINAE
// on std::pair's default constructor.
constexpr explicit DeletedDefault(int x) : value(x) {}
constexpr DeletedDefault() = delete;
int value;
};
template <class Tp, bool>
struct DependantType: public Tp {};
template <class T, bool Val>
using DependantIsDefault = DependantType<std::is_default_constructible<T>, Val>;
template <class T>
struct DefaultSFINAES {
template <bool Dummy = false, class = typename std::enable_if<
DependantIsDefault<T, Dummy>::value
>::type
>
constexpr DefaultSFINAES() : value() {}
constexpr explicit DefaultSFINAES(T const& x) : value(x) {}
T value;
};
struct NoDefault {
constexpr NoDefault(int v) : value(v) {}
int value;
};
template <class Tp>
void test_not_is_default_constructible()
{
{
typedef std::pair<int, Tp> P;
static_assert(!std::is_default_constructible<P>::value, "");
static_assert(std::is_constructible<P, int, Tp>::value, "");
}
{
typedef std::pair<Tp, int> P;
static_assert(!std::is_default_constructible<P>::value, "");
static_assert(std::is_constructible<P, Tp, int>::value, "");
}
{
typedef std::pair<Tp, Tp> P;
static_assert(!std::is_default_constructible<P>::value, "");
static_assert(std::is_constructible<P, Tp, Tp>::value, "");
}
}
template <class Tp>
void test_is_default_constructible()
{
{
typedef std::pair<int, Tp> P;
static_assert(std::is_default_constructible<P>::value, "");
}
{
typedef std::pair<Tp, int> P;
static_assert(std::is_default_constructible<P>::value, "");
}
{
typedef std::pair<Tp, Tp> P;
static_assert(std::is_default_constructible<P>::value, "");
}
}
template <class T>
struct IllFormedDefaultImp {
constexpr explicit IllFormedDefaultImp(int v) : value(v) {}
constexpr IllFormedDefaultImp() : value(T::DoesNotExistAndShouldNotCompile) {}
int value;
};
typedef IllFormedDefaultImp<int> IllFormedDefault;
// A class which provides a constexpr default constructor with a valid
// signature but an ill-formed body. The A compile error will be emitted if
// the default constructor is instantiated.
// Check that the SFINAE on the default constructor is not evaluated when
// it isn't needed. If the default constructor of 'IllFormedDefault' is evaluated
// in C++11, even with is_default_constructible, then this test should fail to
// compile. In C++14 and greater evaluate each test is evaluated as a constant
// expression.
// See LWG issue #2367
void test_illformed_default()
{
{
typedef std::pair<IllFormedDefault, int> P;
static_assert((std::is_constructible<P, IllFormedDefault, int>::value), "");
CONSTEXPR_CXX14 P p(IllFormedDefault(42), -5);
STATIC_ASSERT_CXX14(p.first.value == 42 && p.second == -5);
}
{
typedef std::pair<int, IllFormedDefault> P;
static_assert((std::is_constructible<P, int, IllFormedDefault>::value), "");
CONSTEXPR_CXX14 IllFormedDefault dd(-5);
CONSTEXPR_CXX14 P p(42, dd);
STATIC_ASSERT_CXX14(p.first == 42 && p.second.value == -5);
}
{
typedef std::pair<IllFormedDefault, IllFormedDefault> P;
static_assert((std::is_constructible<P, IllFormedDefault, IllFormedDefault>::value), "");
CONSTEXPR_CXX14 P p(IllFormedDefault(42), IllFormedDefault(-5));
STATIC_ASSERT_CXX14(p.first.value == 42 && p.second.value == -5);
}
}
int main(int, char**)
{
{
// Check that pair<T, U> can still be used even if
// is_default_constructible<T> or is_default_constructible<U> cause
// a compilation error.
test_illformed_default();
}
{
// pair::pair() is only disable in C++11 and beyond.
test_not_is_default_constructible<NoDefault>();
test_not_is_default_constructible<DeletedDefault>();
test_not_is_default_constructible<DefaultSFINAES<int&>>();
test_not_is_default_constructible<DefaultSFINAES<int&&>>();
test_not_is_default_constructible<int&>();
test_not_is_default_constructible<int&&>();
}
{
test_is_default_constructible<int>();
test_is_default_constructible<DefaultSFINAES<int>>();
}
return 0;
}
|