166 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			166 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===----------------------------------------------------------------------===//
 | |
| //
 | |
| // 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;
 | |
| }
 |