Index: include/tuple =================================================================== --- include/tuple +++ include/tuple @@ -751,7 +751,7 @@ _CheckArgsConstructor< !_EnableImplicitReducedArityExtension && sizeof...(_Up) < sizeof...(_Tp) - && !_PackExpandsToThisTuple<_Up...>() + && !_PackExpandsToThisTuple<_Up...>::value >::template __enable_implicit<_Up...>(), bool >::type = false Index: test/std/utilities/tuple/tuple.tuple/tuple.cnstr/reduce_arity_confusion.pass.cpp =================================================================== --- /dev/null +++ test/std/utilities/tuple/tuple.tuple/tuple.cnstr/reduce_arity_confusion.pass.cpp @@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// template class tuple; + +// tuple(tuple const&); +// tuple(tuple&&); +// template +// tuple(UTypes&&... u); +// Check that there is no confusion between reduced arity constructors and +// copy/move constructors. + +// UNSUPPORTED: c++98, c++03 + +#include +#include + +struct Empty {}; + +struct TupleConvertible { + TupleConvertible() : value(0) {} + TupleConvertible(const std::tuple&) : value(1) {} + TupleConvertible(std::tuple&&) : value(1) {} + TupleConvertible(const TupleConvertible&) : value(2) {} + TupleConvertible(TupleConvertible&&) : value(3) {} + int value; +}; + +int main() { + using Tuple = std::tuple; + Tuple x{TupleConvertible(), Empty()}; + // Test that move constructor is preferred to reduced arity constructor + Tuple y(std::move(x)); + assert(std::get<0>(y).value == 3); + // Test that copy constructor is preferred to reduced arity constructor + Tuple z1((const Tuple&)y); + assert(std::get<0>(z1).value == 2); + Tuple z2((Tuple&)y); + assert(std::get<0>(z2).value == 2); + Tuple z3((const Tuple)y); + assert(std::get<0>(z3).value == 2); + Tuple z4(y); + assert(std::get<0>(z4).value == 2); +}