diff options
author | Eric Fiselier <eric@efcs.ca> | 2016-07-02 00:58:17 +0000 |
---|---|---|
committer | Eric Fiselier <eric@efcs.ca> | 2016-07-02 00:58:17 +0000 |
commit | 7b60958aea770570db3833b78bee10ee04b43cee (patch) | |
tree | f8001c240e597f3860e074266adb9aed496cf314 | |
parent | 9c3aec2035f191d0f7bd7511d72c092e3e00b081 (diff) | |
download | bcm5719-llvm-7b60958aea770570db3833b78bee10ee04b43cee.tar.gz bcm5719-llvm-7b60958aea770570db3833b78bee10ee04b43cee.zip |
Make tuple_constructible and family lazy again.
llvm-svn: 274413
-rw-r--r-- | libcxx/include/__tuple | 12 | ||||
-rw-r--r-- | libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/test_lazy_sfinae.pass.cpp | 102 |
2 files changed, 111 insertions, 3 deletions
diff --git a/libcxx/include/__tuple b/libcxx/include/__tuple index 2cd52847796..0d180c70159 100644 --- a/libcxx/include/__tuple +++ b/libcxx/include/__tuple @@ -373,21 +373,27 @@ using __all = is_same<__all_dummy<_Pred...>, __all_dummy<(_Pred, true)...>>; struct __tuple_sfinae_base { template <class ..._FromArgs, class ..._ToArgs> static auto __test_constructible(__tuple_types<_FromArgs...>, __tuple_types<_ToArgs...>) - -> __all<is_constructible<_ToArgs, _FromArgs>::value...>; + -> __all<typename enable_if< + is_constructible<_ToArgs, _FromArgs>::value + , bool>::type{true}...>; static auto __test_constructible(...) -> false_type; template <class _Types1, class _Types2> using __constructible = decltype(__test_constructible(_Types1{}, _Types2{})); template <class ..._FromArgs, class ..._ToArgs> static auto __test_convertible(__tuple_types<_FromArgs...>, __tuple_types<_ToArgs...>) - -> __all<is_convertible<_FromArgs, _ToArgs>::value...>; + -> __all<typename enable_if< + is_convertible<_FromArgs, _ToArgs>::value + , bool>::type{true}...>; static auto __test_convertible(...) -> false_type; template <class _Types1, class _Types2> using __convertible = decltype(__test_convertible(_Types1{}, _Types2{})); template <class ..._FromArgs, class ..._ToArgs> static auto __test_assignable(__tuple_types<_FromArgs...>, __tuple_types<_ToArgs...>) - -> __all<is_assignable<_ToArgs&, _FromArgs>::value...>; + -> __all<typename enable_if< + is_assignable<_ToArgs&, _FromArgs>::value + , bool>::type{true}...>; static auto __test_assignable(...) -> false_type; template <class _Types1, class _Types2> using __assignable = decltype(__test_assignable(_Types1{}, _Types2{})); diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/test_lazy_sfinae.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/test_lazy_sfinae.pass.cpp new file mode 100644 index 00000000000..76f7e794a8e --- /dev/null +++ b/libcxx/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. +// +//===----------------------------------------------------------------------===// + +// <tuple> + +// template <class... Types> class tuple; + +// UNSUPPORTED: c++98, c++03 + +#include <tuple> +#include <utility> +#include <cassert> + +template <class ConstructFrom> +struct ConstructibleFromT { + ConstructibleFromT() = default; + ConstructibleFromT(ConstructFrom v) : value(v) {} + ConstructFrom value; +}; + +template <class AssertOn> +struct CtorAssertsT { + bool defaulted; + CtorAssertsT() : defaulted(true) {} + template <class T> + constexpr CtorAssertsT(T) : defaulted(false) { + static_assert(!std::is_same<T, AssertOn>::value, ""); + } +}; + +template <class AllowT, class AssertT> +struct AllowAssertT { + AllowAssertT() = default; + AllowAssertT(AllowT) {} + template <class U> + constexpr AllowAssertT(U) { + static_assert(!std::is_same<U, AssertT>::value, ""); + } +}; + +// Construct a tuple<T1, T2> from pair<int, int> 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<Tn, int> +// (2) tuple(UTypes...) -> checks is_constructible<T1, pair<int, int>> +// and is_default_constructible<T2> +// The point of this test is to ensure that the consideration of (1) +// short circuits before evaluating is_constructible<T2, int>, 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<std::pair<int, int>>; + using T2 = CtorAssertsT<int>; + std::pair<int, int> p(42, 100); + std::tuple<T1, T2> 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 <class T> +struct BlowsUpOnConstCopy { + BlowsUpOnConstCopy() = default; + constexpr BlowsUpOnConstCopy(BlowsUpOnConstCopy const&) { + static_assert(!std::is_same<T, T>::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<int> b; + std::tuple<NonConstCopyable, BlowsUpOnConstCopy<int>> t(v, b); + assert(std::get<0>(t).value == 42); +} + +int main() { + test_tuple_like_lazy_sfinae(); + test_const_Types_lazy_sfinae(); +} |