Index: include/__config =================================================================== --- include/__config +++ include/__config @@ -305,6 +305,10 @@ #define _LIBCPP_UNUSED __attribute__((__unused__)) +#if !(__has_feature(cxx_default_function_template_args)) +#define _LIBCPP_HAS_NO_DEFAULT_FUNCTION_TEMPLATE_ARGS +#endif + #if !(__has_feature(cxx_defaulted_functions)) #define _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS #endif // !(__has_feature(cxx_defaulted_functions)) @@ -474,6 +478,7 @@ #define _LIBCPP_HAS_NO_ADVANCED_SFINAE #define _LIBCPP_HAS_NO_DECLTYPE +#define _LIBCPP_HAS_NO_DEFAULT_FUNCTION_TEMPLATE_ARGS #define _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS #define _LIBCPP_HAS_NO_DELETED_FUNCTIONS #define _LIBCPP_HAS_NO_NULLPTR @@ -487,13 +492,12 @@ #else // __GXX_EXPERIMENTAL_CXX0X__ #if _GNUC_VER < 403 +#define _LIBCPP_HAS_NO_DEFAULT_FUNCTION_TEMPLATE_ARGS #define _LIBCPP_HAS_NO_RVALUE_REFERENCES -#endif - -#if _GNUC_VER < 403 #define _LIBCPP_HAS_NO_STATIC_ASSERT #endif + #if _GNUC_VER < 404 #define _LIBCPP_HAS_NO_DECLTYPE #define _LIBCPP_HAS_NO_DELETED_FUNCTIONS @@ -565,6 +569,7 @@ #define _LIBCPP_NORETURN __attribute__((noreturn)) #define _LIBCPP_UNUSED +#define _LIBCPP_HAS_NO_DEFAULT_FUNCTION_TEMPLATE_ARGS #define _LIBCPP_HAS_NO_TEMPLATE_ALIASES #define _LIBCPP_HAS_NO_ADVANCED_SFINAE #define _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS Index: include/utility =================================================================== --- include/utility +++ include/utility @@ -269,6 +269,12 @@ // pair(const pair&) = default; // pair(pair&&) = default; +#ifndef _LIBCPP_HAS_NO_DEFAULT_FUNCTION_TEMPLATE_ARGS + template , _Dummy>::value && + __dependent_type, _Dummy>::value + >::type> +#endif _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR pair() : first(), second() {} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 Index: test/std/utilities/utility/pairs/pairs.pair/default.pass.cpp =================================================================== --- test/std/utilities/utility/pairs/pairs.pair/default.pass.cpp +++ test/std/utilities/utility/pairs/pairs.pair/default.pass.cpp @@ -14,8 +14,128 @@ // constexpr pair(); #include +#include #include +#include "test_macros.h" + + +#if TEST_STD_VER > 11 +#define CONSTEXPR_CXX14 constexpr + // Expands to 'constexpr' in C++14 and greater and '' otherwise. +#define STATIC_ASSERT_CXX14(Pred) static_assert(Pred, "") + // Assert the specified expression 'Pred' using a static_assert in C++14 and + // greater and using assert(...) otherwise. +#else +#define CONSTEXPR_CXX14 +#define STATIC_ASSERT_CXX14(Pred) assert(Pred) +#endif + +#if TEST_STD_VER >= 11 +#define ASSERT_CXX03_ONLY(Pred) ((void)0) + // Assert the specified expression 'Pred' only in C++98 and C++03. In C++11 + // and greater 'ASSERT_CXX03_ONLY' expands to a nop expression. +#else +#define ASSERT_CXX03_ONLY(Pred) assert(Pred) +#endif + + +#if TEST_STD_VER >= 11 +struct DeletedDefault { + // A class with a deleted default constructor. Used to test the SFINAE + // on std::pairs default constructor. + constexpr explicit DeletedDefault(int x) : value(x) {} + constexpr DeletedDefault() = delete; + int value; +}; +#endif + +template +struct IllFormedDefaultImp { + TEST_CONSTEXPR explicit IllFormedDefaultImp(int v) : value(v) {} + TEST_CONSTEXPR IllFormedDefaultImp() : value(T::DoesNotExistAndShouldNotCompile) {} + int value; +}; + +typedef IllFormedDefaultImp 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. + + +// Test that the defaulted constructor does not participate in overload +// resolution when either of the types in the pair is not default constructible. +// See LWG issue #2367 +void test_deleted_default() +{ +#if TEST_STD_VER >= 11 + { + typedef std::pair P; + static_assert(std::is_default_constructible

::value, ""); + static_assert(std::is_constructible

::value, ""); + } + { + typedef std::pair P; + static_assert(!std::is_default_constructible

::value, ""); + static_assert(!std::is_constructible

::value, ""); + static_assert(std::is_constructible::value, ""); + CONSTEXPR_CXX14 P p(DeletedDefault(42), -5); + STATIC_ASSERT_CXX14(p.first.value == 42 && p.second == -5); + } + { + typedef std::pair P; + static_assert(!std::is_default_constructible

::value, ""); + static_assert(!std::is_constructible

::value, ""); + static_assert(std::is_constructible::value, ""); + constexpr DeletedDefault dd(-5); + CONSTEXPR_CXX14 P p(42, dd); + STATIC_ASSERT_CXX14(p.first == 42 && p.second.value == -5); + } + { + typedef std::pair P; + static_assert(!std::is_default_constructible

::value, ""); + static_assert(std::is_constructible::value, ""); + CONSTEXPR_CXX14 P p(DeletedDefault(42), DeletedDefault(-5)); + STATIC_ASSERT_CXX14(p.first.value == 42 && p.second.value == -5); + } +#endif +} + + +// 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. In C++03 evaluating is_default_constructible will compile return the +// wrong answer because libc++ does not back-port this behavior. +// See LWG issue #2367 +void test_illformed_default() +{ + { + typedef std::pair P; + static_assert((std::is_constructible::value), ""); + CONSTEXPR_CXX14 P p(IllFormedDefault(42), -5); + STATIC_ASSERT_CXX14(p.first.value == 42 && p.second == -5); + ASSERT_CXX03_ONLY(std::is_default_constructible

::value); // ASSERTS BUG IN C++03 + } + { + typedef std::pair P; + static_assert((std::is_constructible::value), ""); + CONSTEXPR_CXX14 IllFormedDefault dd(-5); + CONSTEXPR_CXX14 P p(42, dd); + STATIC_ASSERT_CXX14(p.first == 42 && p.second.value == -5); + ASSERT_CXX03_ONLY(std::is_default_constructible

::value); // ASSERTS BUG IN C++03 + } + { + typedef std::pair P; + static_assert((std::is_constructible::value), ""); + CONSTEXPR_CXX14 P p(IllFormedDefault(42), IllFormedDefault(-5)); + STATIC_ASSERT_CXX14(p.first.value == 42 && p.second.value == -5); + ASSERT_CXX03_ONLY(std::is_default_constructible

::value); // ASSERTS BUG IN C++03 + } +} + + int main() { { @@ -24,8 +144,7 @@ assert(p.first == 0.0f); assert(p.second == nullptr); } - -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER >= 11 { typedef std::pair P; constexpr P p; @@ -33,4 +152,6 @@ static_assert(p.second == nullptr, ""); } #endif + test_deleted_default(); + test_illformed_default(); }