diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple index 59b992a..751d7eb 100644 --- a/libstdc++-v3/include/std/tuple +++ b/libstdc++-v3/include/std/tuple @@ -486,6 +486,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __and_...>::value; } + + template + static constexpr bool _NonNestedTuple() + { + return __and_<__not_>, + __not_> + >::value; + } }; template @@ -514,6 +522,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return false; } + + template + static constexpr bool _NonNestedTuple() + { + return true; + } }; /// Primary class template, tuple @@ -599,40 +613,54 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr tuple(tuple&&) = default; - template using _TNTC = + _TC::value && sizeof...(_Elements) == 1, + _Elements...>; + + template::template _ConstructibleTuple<_UElements...>() && _TMC<_UElements...>::template - _ImplicitlyConvertibleTuple<_UElements...>(), + _ImplicitlyConvertibleTuple<_UElements...>() + && _TNTC<_Dummy>::template + _NonNestedTuple&>(), bool>::type=true> constexpr tuple(const tuple<_UElements...>& __in) : _Inherited(static_cast&>(__in)) { } - template::template _ConstructibleTuple<_UElements...>() && !_TMC<_UElements...>::template - _ImplicitlyConvertibleTuple<_UElements...>(), + _ImplicitlyConvertibleTuple<_UElements...>() + && _TNTC<_Dummy>::template + _NonNestedTuple&>(), bool>::type=false> explicit constexpr tuple(const tuple<_UElements...>& __in) : _Inherited(static_cast&>(__in)) { } - template::template _MoveConstructibleTuple<_UElements...>() && _TMC<_UElements...>::template - _ImplicitlyMoveConvertibleTuple<_UElements...>(), + _ImplicitlyMoveConvertibleTuple<_UElements...>() + && _TNTC<_Dummy>::template + _NonNestedTuple&&>(), bool>::type=true> constexpr tuple(tuple<_UElements...>&& __in) : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { } - template::template _MoveConstructibleTuple<_UElements...>() && !_TMC<_UElements...>::template - _ImplicitlyMoveConvertibleTuple<_UElements...>(), + _ImplicitlyMoveConvertibleTuple<_UElements...>() + && _TNTC<_Dummy>::template + _NonNestedTuple&&>(), bool>::type=false> explicit constexpr tuple(tuple<_UElements...>&& __in) : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { } diff --git a/libstdc++-v3/testsuite/20_util/tuple/cons/nested_tuple_construct.cc b/libstdc++-v3/testsuite/20_util/tuple/cons/nested_tuple_construct.cc new file mode 100644 index 0000000..32ef3cc --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/tuple/cons/nested_tuple_construct.cc @@ -0,0 +1,60 @@ +#include +#include +#include + +static std::string result; + +struct X { + int state; // this has to be here + X() { + result += "Def"; + } + + X(X const&) { + result += "Copy"; + } + + X(X&&) { + result += "Move"; + } + + ~X() { + result += "Dtor"; + } +}; + +void f() +{ + X v; + std::tuple t1{v}; + std::tuple&&> t2{std::move(t1)}; + std::tuple> t3{std::move(t2)}; +} + +void f2() +{ + X v; + std::tuple t1{std::move(v)}; + std::tuple&&> t2{std::move(t1)}; + std::tuple> t3{std::move(t2)}; +} + +void f3() +{ + std::tuple t1{X{}}; + std::tuple&&> t2{std::move(t1)}; + std::tuple> t3{std::move(t2)}; +} + +int main() +{ + f(); + VERIFY(result == "DefCopyMoveDtorDtorDtor"); + result = ""; + f2(); + VERIFY(result == "DefMoveMoveDtorDtorDtor"); + result = ""; + f3(); + VERIFY(result == "DefMoveDtorMoveDtorDtor"); + result = ""; +}