https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90700

            Bug ID: 90700
           Summary: Wrong constraints for tuple(allocator_arg_t, const A&,
                    const tuple<UTypes...>&)
           Product: gcc
           Version: 10.0
            Status: UNCONFIRMED
          Keywords: rejects-valid
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: redi at gcc dot gnu.org
  Target Milestone: ---

This should compile:

#include <tuple>
#include <memory>

struct X { };

struct Y
{
  Y(const std::tuple<X>&) = delete;
  Y(std::tuple<X>&&) { throw 1; }
  Y(const X&) { }
};

int main()
{
  const std::allocator<int> a;
  std::tuple<X> x;

  static_assert(!std::is_convertible<const std::tuple<X>&, Y>::value, "");
  static_assert(!std::is_constructible<Y, const std::tuple<X>&>::value, "");
  static_assert(!std::is_same<Y, X>::value, "");
  // should use tuple<Y>::tuple<X>(allocator_arg_t, const A&, const tuple<X>&)
  // and construct Y from X:
  std::tuple<Y> y(std::allocator_arg, a, x);
}

tup.cc: In function 'int main()':
tup.cc:23:43: error: call of overloaded 'tuple(const std::allocator_arg_t&,
const std::allocator<int>&, std::tuple<X>&)' is ambiguous
   23 |   std::tuple<Y> y(std::allocator_arg, a, x);
      |                                           ^
In file included from tup.cc:1:
/home/jwakely/gcc/9/include/c++/9.1.1/tuple:751:2: note: candidate:
'std::tuple<_Elements>::tuple(std::allocator_arg_t, const _Alloc&,
std::tuple<_Elements>&&) [with _Alloc = std::allocator<int>; _Elements = {Y}]'
  751 |  tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
      |  ^~~~~
/home/jwakely/gcc/9/include/c++/9.1.1/tuple:747:2: note: candidate:
'std::tuple<_Elements>::tuple(std::allocator_arg_t, const _Alloc&, const
std::tuple<_Elements>&) [with _Alloc = std::allocator<int>; _Elements = {Y}]'
  747 |  tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
      |  ^~~~~
/home/jwakely/gcc/9/include/c++/9.1.1/tuple:709:2: note: candidate:
'std::tuple<_Elements>::tuple(std::allocator_arg_t, const _Alloc&, const
_Elements& ...) [with _Alloc = std::allocator<int>; _Dummy = void; typename
std::enable_if<(std::_TC<std::is_same<_Dummy, void>::value, _Elements
...>::_ConstructibleTuple<_Elements ...>() && std::_TC<std::is_same<_Dummy,
void>::value, _Elements ...>::_ImplicitlyConvertibleTuple<_Elements ...>()),
bool>::type <anonymous> = true; _Elements = {Y}]'
  709 |  tuple(allocator_arg_t __tag, const _Alloc& __a,
      |  ^~~~~
tup.cc:23:17: warning: unused variable 'y' [-Wunused-variable]
   23 |   std::tuple<Y> y(std::allocator_arg, a, x);
      |                 ^


The problem is that the wrong value category is used in the constraints for the
tuple(allocator_arg_t, const A&, const tuple<UTypes...>&) constructor:

--- a/libstdc++-v3/include/std/tuple
+++ b/libstdc++-v3/include/std/tuple
@@ -774,7 +774,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
                   && _TMCT<_UElements...>::template
                     _ImplicitlyConvertibleTuple<_UElements...>()
                   && _TNTC<_Dummy>::template
-                    _NonNestedTuple<tuple<_UElements...>&&>(),
+                    _NonNestedTuple<const tuple<_UElements...>&>(),
         bool>::type=true>
        tuple(allocator_arg_t __tag, const _Alloc& __a,
              const tuple<_UElements...>& __in)
@@ -789,7 +789,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
                   && !_TMCT<_UElements...>::template
                     _ImplicitlyConvertibleTuple<_UElements...>()
                   && _TNTC<_Dummy>::template
-                    _NonNestedTuple<tuple<_UElements...>&&>(),
+                    _NonNestedTuple<const tuple<_UElements...>&>(),
         bool>::type=false>
        explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
              const tuple<_UElements...>& __in)

Reply via email to