From cebaf5cbf8a8bfeb74bd1c82549f1773f84b5474 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Sat, 2 Jul 2016 00:58:17 +0000 Subject: [PATCH] Make tuple_constructible and family lazy again. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@274413 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/__tuple | 12 ++- .../tuple.cnstr/test_lazy_sfinae.pass.cpp | 102 ++++++++++++++++++ 2 files changed, 111 insertions(+), 3 deletions(-) create mode 100644 test/std/utilities/tuple/tuple.tuple/tuple.cnstr/test_lazy_sfinae.pass.cpp diff --git a/include/__tuple b/include/__tuple index 2cd528477..0d180c701 100644 --- a/include/__tuple +++ b/include/__tuple @@ -373,21 +373,27 @@ using __all = is_same<__all_dummy<_Pred...>, __all_dummy<(_Pred, true)...>>; struct __tuple_sfinae_base { template static auto __test_constructible(__tuple_types<_FromArgs...>, __tuple_types<_ToArgs...>) - -> __all::value...>; + -> __all::value + , bool>::type{true}...>; static auto __test_constructible(...) -> false_type; template using __constructible = decltype(__test_constructible(_Types1{}, _Types2{})); template static auto __test_convertible(__tuple_types<_FromArgs...>, __tuple_types<_ToArgs...>) - -> __all::value...>; + -> __all::value + , bool>::type{true}...>; static auto __test_convertible(...) -> false_type; template using __convertible = decltype(__test_convertible(_Types1{}, _Types2{})); template static auto __test_assignable(__tuple_types<_FromArgs...>, __tuple_types<_ToArgs...>) - -> __all::value...>; + -> __all::value + , bool>::type{true}...>; static auto __test_assignable(...) -> false_type; template using __assignable = decltype(__test_assignable(_Types1{}, _Types2{})); diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/test_lazy_sfinae.pass.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/test_lazy_sfinae.pass.cpp new file mode 100644 index 000000000..76f7e794a --- /dev/null +++ b/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/test_lazy_sfinae.pass.cpp @@ -0,0 +1,102 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// template class tuple; + +// UNSUPPORTED: c++98, c++03 + +#include +#include +#include + +template +struct ConstructibleFromT { + ConstructibleFromT() = default; + ConstructibleFromT(ConstructFrom v) : value(v) {} + ConstructFrom value; +}; + +template +struct CtorAssertsT { + bool defaulted; + CtorAssertsT() : defaulted(true) {} + template + constexpr CtorAssertsT(T) : defaulted(false) { + static_assert(!std::is_same::value, ""); + } +}; + +template +struct AllowAssertT { + AllowAssertT() = default; + AllowAssertT(AllowT) {} + template + constexpr AllowAssertT(U) { + static_assert(!std::is_same::value, ""); + } +}; + +// Construct a tuple from pair where T1 and T2 +// are not constructible from ints but T1 is constructible from std::pair. +// This considers the following constructors: +// (1) tuple(TupleLike) -> checks is_constructible +// (2) tuple(UTypes...) -> checks is_constructible> +// and is_default_constructible +// The point of this test is to ensure that the consideration of (1) +// short circuits before evaluating is_constructible, which +// will cause a static assertion. +void test_tuple_like_lazy_sfinae() { +#if defined(_LIBCPP_VERSION) + // This test requires libc++'s reduced arity initialization. + using T1 = ConstructibleFromT>; + using T2 = CtorAssertsT; + std::pair p(42, 100); + std::tuple t(p); + assert(std::get<0>(t).value == p); + assert(std::get<1>(t).defaulted); +#endif +} + + +struct NonConstCopyable { + NonConstCopyable() = default; + explicit NonConstCopyable(int v) : value(v) {} + NonConstCopyable(NonConstCopyable&) = default; + NonConstCopyable(NonConstCopyable const&) = delete; + int value; +}; + +template +struct BlowsUpOnConstCopy { + BlowsUpOnConstCopy() = default; + constexpr BlowsUpOnConstCopy(BlowsUpOnConstCopy const&) { + static_assert(!std::is_same::value, ""); + } + BlowsUpOnConstCopy(BlowsUpOnConstCopy&) = default; +}; + +// Test the following constructors: +// (1) tuple(Types const&...) +// (2) tuple(UTypes&&...) +// Test that (1) short circuits before evaluating the copy constructor of the +// second argument. Constructor (2) should be selected. +void test_const_Types_lazy_sfinae() +{ + NonConstCopyable v(42); + BlowsUpOnConstCopy b; + std::tuple> t(v, b); + assert(std::get<0>(t).value == 42); +} + +int main() { + test_tuple_like_lazy_sfinae(); + test_const_Types_lazy_sfinae(); +}