[libcxx] Fix LWG Issue #2367 - Fixing std::tuple and std::pair's default constructors.
Summary: This patch implements the solution for LWG Issue #2367. See http://cplusplus.github.io/LWG/lwg-active.html#2367 Reviewers: mclow.lists, EricWF Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D13750 llvm-svn: 256325
This commit is contained in:
parent
7b46b4e798
commit
7a608aa232
|
@ -305,6 +305,10 @@ typedef __char32_t char32_t;
|
|||
|
||||
#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 @@ namespace std {
|
|||
|
||||
#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 @@ namespace std {
|
|||
#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 @@ namespace std {
|
|||
#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
|
||||
|
|
|
@ -288,6 +288,12 @@ struct _LIBCPP_TYPE_VIS_ONLY pair
|
|||
// pair(const pair&) = default;
|
||||
// pair(pair&&) = default;
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_DEFAULT_FUNCTION_TEMPLATE_ARGS
|
||||
template <bool _Dummy = true, class = typename enable_if<
|
||||
__dependent_type<is_default_constructible<_T1>, _Dummy>::value &&
|
||||
__dependent_type<is_default_constructible<_T2>, _Dummy>::value
|
||||
>::type>
|
||||
#endif
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR pair() : first(), second() {}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
|
|
|
@ -0,0 +1,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::pairs 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>>();
|
||||
}
|
||||
}
|
|
@ -13,9 +13,15 @@
|
|||
|
||||
// constexpr pair();
|
||||
|
||||
// NOTE: The SFINAE on the default constructor is tested in
|
||||
// default-sfinae.pass.cpp
|
||||
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
|
@ -24,13 +30,12 @@ int main()
|
|||
assert(p.first == 0.0f);
|
||||
assert(p.second == nullptr);
|
||||
}
|
||||
|
||||
#if _LIBCPP_STD_VER > 11
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::pair<float, short*> P;
|
||||
constexpr P p;
|
||||
static_assert(p.first == 0.0f, "");
|
||||
static_assert(p.second == nullptr, "");
|
||||
typedef std::pair<float, short*> P;
|
||||
constexpr P p;
|
||||
static_assert(p.first == 0.0f, "");
|
||||
static_assert(p.second == nullptr, "");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue