diff options
author | Eric Fiselier <eric@efcs.ca> | 2015-12-23 08:20:26 +0000 |
---|---|---|
committer | Eric Fiselier <eric@efcs.ca> | 2015-12-23 08:20:26 +0000 |
commit | 7a608aa232c18cefebde9eb5035ccdcc17f58c9d (patch) | |
tree | e84e6f1dbf60ec7f5f0de26bc7835bc82d0f7899 /libcxx/test/std/utilities | |
parent | 7b46b4e7984ebe45e56fe4a54633c0a2cff260fe (diff) | |
download | bcm5719-llvm-7a608aa232c18cefebde9eb5035ccdcc17f58c9d.tar.gz bcm5719-llvm-7a608aa232c18cefebde9eb5035ccdcc17f58c9d.zip |
[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
Diffstat (limited to 'libcxx/test/std/utilities')
-rw-r--r-- | libcxx/test/std/utilities/utility/pairs/pairs.pair/default-sfinae.pass.cpp | 164 | ||||
-rw-r--r-- | libcxx/test/std/utilities/utility/pairs/pairs.pair/default.pass.cpp | 17 |
2 files changed, 175 insertions, 6 deletions
diff --git a/libcxx/test/std/utilities/utility/pairs/pairs.pair/default-sfinae.pass.cpp b/libcxx/test/std/utilities/utility/pairs/pairs.pair/default-sfinae.pass.cpp new file mode 100644 index 00000000000..8f9fc669251 --- /dev/null +++ b/libcxx/test/std/utilities/utility/pairs/pairs.pair/default-sfinae.pass.cpp @@ -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>>(); + } +} diff --git a/libcxx/test/std/utilities/utility/pairs/pairs.pair/default.pass.cpp b/libcxx/test/std/utilities/utility/pairs/pairs.pair/default.pass.cpp index bb6661f7966..d83328b8f2d 100644 --- a/libcxx/test/std/utilities/utility/pairs/pairs.pair/default.pass.cpp +++ b/libcxx/test/std/utilities/utility/pairs/pairs.pair/default.pass.cpp @@ -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 } |