Tested on Linux-PPC64. The problem is a tad tricky, since the bug triggered by the testcase is in a constructor that will not be used, but will cause endless meta-recursion via checking convertibility of an incomplete type that will cause further recursion. While there might be ways to fix that in the traits themselves, this is a straightforward fix, for certain tuple-specific values of "straightforward". ;)
And hey, the problem and its solution were, once the bug report came in, obvious to the resident tuple-hacker between my chair and my keyboard. :) 2015-10-05 Ville Voutilainen <ville.voutilai...@gmail.com> PR 67844. * include/std/tuple (_TC::_NonNestedTuple): Eagerly reject conversions from tuple types same as the target tuple. * testsuite/20_util/tuple/67844.cc: New.
diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple index 751d7eb..8af01f4 100644 --- a/libstdc++-v3/include/std/tuple +++ b/libstdc++-v3/include/std/tuple @@ -457,6 +457,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } }; + template<typename... _Elements> + class tuple; // Concept utility functions, reused in conditionally-explicit // constructors. @@ -490,7 +492,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _SrcTuple> static constexpr bool _NonNestedTuple() { - return __and_<__not_<is_convertible<_SrcTuple, _Elements...>>, + return __and_<__not_<is_same<tuple<_Elements...>, + typename remove_cv< + typename remove_reference<_SrcTuple>::type + >::type>>, + __not_<is_convertible<_SrcTuple, _Elements...>>, __not_<is_constructible<_Elements..., _SrcTuple>> >::value; } diff --git a/libstdc++-v3/testsuite/20_util/tuple/67844.cc b/libstdc++-v3/testsuite/20_util/tuple/67844.cc new file mode 100644 index 0000000..5635462 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/tuple/67844.cc @@ -0,0 +1,24 @@ +// { dg-do compile } + +#include <tuple> + +struct A +{ + template <typename T> + A(T) + { + } + + A(const A&) = default; + A(A&&) = default; + A& operator=(const A&) = default; + A& operator=(A&&) = default; + ~A() = default; +}; + +int main() +{ + auto x = A{7}; + std::make_tuple(x); +} +