Tested on Linux-PPC64. The idea here is to get the constructor templates to step out of the way if what they are dealing with will be handled by a special member function, like the copy constructor. Doing so properly fixes the bug at hand and likely other similar cases, too. The problem in getting the templates out of the way is that none of their is_constructible or is_convertible checks should be evaluated at all, but since we have these handy pseudo-concepts in place, doing that is merely a matter of adjusting the shortcut alias for one of those pseudo-concepts.
2016-05-24 Ville Voutilainen <ville.voutilai...@gmail.com> PR libstdc++/66338 * include/std/tuple (_TMC): Add a check for _NotSameTuple. * include/std/tuple (tuple(_UElements&&...)): Remove the separate check for _NotSameTuple. * testsuite/20_util/tuple/cons/66338.cc: New.
diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple index 7522e43..3cc6a2c 100644 --- a/libstdc++-v3/include/std/tuple +++ b/libstdc++-v3/include/std/tuple @@ -620,14 +620,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Shortcut for the cases where constructors taking _UElements... // need to be constrained. template<typename... _UElements> using _TMC = - _TC<(sizeof...(_Elements) == sizeof...(_UElements)), + _TC<(sizeof...(_Elements) == sizeof...(_UElements)) + && (_TC<(sizeof...(_UElements)==1), _Elements...>:: + template _NotSameTuple<_UElements...>()), _Elements...>; template<typename... _UElements, typename enable_if< - _TC<sizeof...(_UElements) == 1, _Elements...>::template - _NotSameTuple<_UElements...>() - && _TMC<_UElements...>::template + _TMC<_UElements...>::template _MoveConstructibleTuple<_UElements...>() && _TMC<_UElements...>::template _ImplicitlyMoveConvertibleTuple<_UElements...>() @@ -638,9 +638,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename... _UElements, typename enable_if< - _TC<sizeof...(_UElements) == 1, _Elements...>::template - _NotSameTuple<_UElements...>() - && _TMC<_UElements...>::template + _TMC<_UElements...>::template _MoveConstructibleTuple<_UElements...>() && !_TMC<_UElements...>::template _ImplicitlyMoveConvertibleTuple<_UElements...>() diff --git a/libstdc++-v3/testsuite/20_util/tuple/cons/66338.cc b/libstdc++-v3/testsuite/20_util/tuple/cons/66338.cc new file mode 100644 index 0000000..f57eae9 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/tuple/cons/66338.cc @@ -0,0 +1,35 @@ +// Copyright (C) 2016 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include <tuple> + +struct S { + int i_; + + template<typename T> + S(T&& i) + noexcept(noexcept(i_ = i)) + { i_ = i; } + + S() noexcept : i_{0} {}; +}; + +int main() +{ + std::tuple<S&&>(std::forward_as_tuple(S{})); + return 0; +}