| //===----------------------------------------------------------------------===// |
| // |
| // 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>>(); |
| } |
| } |