问题 Rvalue转发引用


我在读 参考折叠规则 我有一个问题:为什么我通过了 右值A. 至

template<typename T>
void foo(T&&);

T推断为A?

例如如果我通过 std::string() 到功能 T 被推断为 std::string, 为什么不 std::string&&?这对我来说更有意义,演绎背后的理由是什么 T 这个类型本身?


967
2018-03-30 11:29


起源



答案:


这仅仅与我们通常从模板类型推导出现的预期相符:

template <class T> void vfoo(T );
template <class T> void lfoo(T& );
template <class T> void cfoo(T const& );
template <class T> void ffoo(T&& );

std::string x;
vfoo(x);            // deduce T = std::string
lfoo(x);            // deduce T = std::string
cfoo(x);            // deduce T = std::string
ffoo(x);            // deduce T = std::string& !
ffoo(std::move(x)); // deduce T = std::string

原始论文,强调我的:

当使用与右值引用匹配的左值参数推导出函数模板类型时,该类型被推导为左值引用类型。当推导出rvalue参数时, 类型演绎与其他类型一样。 

这是一个特殊的左值扣除案例,这就是为什么它在类型扣除规则中得到一个额外的句子。 rvalue案例是典型的 - 它与推导出的类型中粘贴的简单心理模型排列在一起,看看你最终会得到什么功能。叫 T&& 用一个 std::string?得到 T = std::string 所以参数读起来 std::string&&。检查。


11
2018-03-30 11:53





因为函数参数类型上有&&,并且您正在推导表达式的“T”部分。

所以,“通过” std::string&& 至 T&& 将演绎 T 如 std::string

std::string 如 T 在表达中 T&& 产量 std::string&&

它有点像演绎一样 T 在表达中 T const&;当'通过'时 std::string 通过const引用, T 部分推断为 std::string


3
2018-03-30 11:47



你的最后一句话是错的。 template<typename T> void foo(T) 绝不会推断出引用类型。 - Oktalist
@Oktalist你是对的 - 我删除了它。 - Pete


答案:


这仅仅与我们通常从模板类型推导出现的预期相符:

template <class T> void vfoo(T );
template <class T> void lfoo(T& );
template <class T> void cfoo(T const& );
template <class T> void ffoo(T&& );

std::string x;
vfoo(x);            // deduce T = std::string
lfoo(x);            // deduce T = std::string
cfoo(x);            // deduce T = std::string
ffoo(x);            // deduce T = std::string& !
ffoo(std::move(x)); // deduce T = std::string

原始论文,强调我的:

当使用与右值引用匹配的左值参数推导出函数模板类型时,该类型被推导为左值引用类型。当推导出rvalue参数时, 类型演绎与其他类型一样。 

这是一个特殊的左值扣除案例,这就是为什么它在类型扣除规则中得到一个额外的句子。 rvalue案例是典型的 - 它与推导出的类型中粘贴的简单心理模型排列在一起,看看你最终会得到什么功能。叫 T&& 用一个 std::string?得到 T = std::string 所以参数读起来 std::string&&。检查。


11
2018-03-30 11:53





因为函数参数类型上有&&,并且您正在推导表达式的“T”部分。

所以,“通过” std::string&& 至 T&& 将演绎 T 如 std::string

std::string 如 T 在表达中 T&& 产量 std::string&&

它有点像演绎一样 T 在表达中 T const&;当'通过'时 std::string 通过const引用, T 部分推断为 std::string


3
2018-03-30 11:47



你的最后一句话是错的。 template<typename T> void foo(T) 绝不会推断出引用类型。 - Oktalist
@Oktalist你是对的 - 我删除了它。 - Pete