summaryrefslogtreecommitdiffstats
path: root/libcxx/test/std/utilities/utility/pairs/pairs.pair/default-sfinae.pass.cpp
blob: d5e1e232f86f653d2ae1c35b6ed0a1ab46992e6d (plain)
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
//===----------------------------------------------------------------------===//
//
//                     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.
//
//===----------------------------------------------------------------------===//

// <utility>

// template <class T1, class T2> struct pair

// Test the SFINAE required by LWG Issue #2367.
// is_default_constructible<pair>

// UNSUPPORTED: c++98, 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()
{
    {
        // 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>>();
    }
}
OpenPOWER on IntegriCloud