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)