为什么std :: get没有一个接受转发引用的签名

时间:2017-04-04 01:46:01

标签: c++ c++11 c++14 c++17 stdtuple

为什么std::get的{​​{1}}有这么多的重载(http://en.cppreference.com/w/cpp/utility/tuple/get)?一个对应std::tuple const&的每种可能组合?对于每个组合,返回值上的const ref限定符是相同的。为什么不通过转发引用只有一个单一的重载接受元组类型,然后根据输入的签名简单地转发返回值?像这样的东西

&&

这种事情会让人们很容易推断template <int Index, typename TupleType> decltype(auto) get(TupleType&& tup); 函数的作用,并避免像问题2485(https://wg21.cmeerw.net/lwg/issue2485

这样的错误

2 个答案:

答案 0 :(得分:4)

std::get存在于decltype(auto)之前。这很容易。

好的,为什么不改变它?

std::get的主体未由标准指定,并且不应该因为不同的编译器具有不同的元组布局和实现。

decltype(auto)没有告诉读者标准,编译器的用户或实现者,返回类型是什么。它只是说它是从身体推断出来的。标准没有指定。

它在标准中就像那样没用,除非他们分别描述了返回值是什么,最终看起来很像列出重载。

答案 1 :(得分:2)

无法推断出std::get的参数,因为std::get是针对许多不同类型定义的。 (例如tuplepairarrayvariant)。

因此,任何其他std::get都不能推断出其参数类型。此时将其更改为演绎会破坏现实世界的代码,例如从元组推导出的类型。例如,建议的签名更改将产生如下签名: template <class TupleLike, class = enable_if_t<IsStdTuple<TupleLike>::value>>> decltype(auto) get(TupleLike&&);

此签名不允许对接口中的元组类型进行隐式转换,就像旧签名一样。如上所述,这会将从std::tuple派生的类型或具有转化运算符的类型分解为std::tuple

Libc ++使用单个通用tuple重载实现pairarrayTupleLike转换构造函数。作为维护者,我非常熟悉这些实现问题,如果我能按照你的建议实现一致的std::get,我已经这样了。