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;
+}

Reply via email to