【发布时间】:2021-12-25 02:18:59
【问题描述】:
“转发引用”用引号引起来,因为const-qualified 转发引用实际上并不是转发引用,但我想明确表示我特别指的是函数模板。 p>
采取以下测试功能(代码重复以避免:
#include <iostream>
#include <type_traits>
#include <typeinfo>
using namespace std;
template <typename T, typename U> void print_types() {
cout << (is_const_v<remove_reference_t<T>> ? "const " : "")
<< typeid(T).name()
<< (is_rvalue_reference_v<T> ? " &&"
: is_lvalue_reference_v<T> ? " &"
: "")
<< ", " << (is_const_v<remove_reference_t<U>> ? "const " : "")
<< typeid(U).name()
<< (is_rvalue_reference_v<U> ? " &&"
: is_lvalue_reference_v<U> ? " &"
: "")
<< endl;
}
template <typename T> void print_rvalue_reference(T &&t) {
print_types<T, decltype(t)>();
}
template <typename T> void print_const_rvalue_reference(const T &&t) {
print_types<T, decltype(t)>();
}
int main() {
int i = 1;
const int j = 1;
print_rvalue_reference(1); // int, int &&
print_rvalue_reference(i); // int &, int &
print_rvalue_reference(j); // const int &, const int &
print_const_rvalue_reference(1); // int, const int &&
print_const_rvalue_reference(i); // error
print_const_rvalue_reference(j); // error
}
首先,我想指出 print_rvalue_reference(j) 之所以有效,是因为 print_rvalue_reference 从不在非 const 上下文中使用 t。如果不是这种情况,模板实例化就会失败。
我很困惑为什么main 中的最后两个调用会在编译期间导致错误。引用折叠允许using T = int &; const T && 变为int & 和using T = const int &; const T && 变为const int &,这意味着print_const_rvalue_reference<int &>(i) 和print_const_rvalue_reference<const int &>(j) 是有效的。
当print_rvalue_reference(j)确实推导出T是const int &时,为什么print_const_rvalue_reference(j)推导出T是int而不是const int &? (真实的)转发引用是否特例以产生int & 而不是int 作为其推导指南的一部分?
【问题讨论】:
-
template <typename T> void print_const_rvalue_reference(const T &&t)T 不是转发/通用引用,只能绑定到一个 R 值 -
@doug 正如我在第一段中所述,我知道
const T &&不是转发参考。但是,您提到的函数可以绑定到左值:int i; print_const_rvalue_reference<int &>(i);有效,print_const_rvalue_reference<const int &>(i)也有效。 -
print_const_rvalue_reference(const T && i);只能绑定到 R 值。例如,这将起作用:print_const_rvalue_reference(+i);,因为一元运算符 + 使表达式 +i 成为 R 值。 -
@doug 我只是给出了两个函数绑定到左值的例子......
-
强调了我的一点小烦恼:我们经常听到通用/转发引用因为引用折叠而起作用。这是真的,但另一点,至少同样重要,使它们起作用的是模板参数推导有其特殊情况规则,专门用于具有左值参数的转发引用。