通用参考的语法
这是一个右值参考:
void foo(int&& a);
它不绑定到左值:
int i = 42;
foo(i); // error
这是一个普遍的参考:
template<typename T>
void bar(T&& b);
它绑定到右值,它也绑定到左值:
bar(i); // okay
这是一个右值参考:
template<typename T>
struct X
{
void baz(T&& c);
};
它不绑定到左值:
X<int> x;
x.baz(i); // error
为什么通用引用使用与右值引用相同的语法? 这不是一个不必要的混乱来源吗? 委员会是否考虑过T&&&
, T&*
, T@
或T&42
等替代语法(只是在最后一个开玩笑)? 如果是这样,拒绝替代语法的原因是什么?
像T&&
这样的通用参考可以推断T
是一个“对象类型”或“参考类型”
在你的例子中,当传递一个右值时,它可以推导出T
为int
,所以函数参数是int&&
,或者它可以推导T
为int&
当传递一个左值时,在这种情况下函数参数是int&
(因为参考折叠规则说std::add_rvalue_reference<int&>::type
只是int&
)
如果T
不是由函数调用推导出来的(如在你的X::baz
例子中)那么它不能被推导为int&
,所以引用不是通用的引用。
所以恕我直言,真的不需要新的语法,它很好地适用于模板参数推导和参考折叠规则,并且可以将模板参数推导为参考类型(C ++ 03中的函数模板参数类型T
或T&
总是推断T
作为对象类型。)
这些语义和语法从一开始就被提出,当右值引用和对参数推导规则的调整被提议作为转发问题的解决方案时,参见N1385。 为了达到移动语义的目的,提出使用这种语法来提供完美的转发,并提出了右值引用:N1377与N1385的邮件地址相同。 我认为没有其他的语法被认真提出过。
恕我直言,替代语法实际上会更混乱。 如果你有template<typename T> void bar(T&@)
作为通用引用的语法,但是与我们现在具有相同的语义,那么当调用bar(i)
,模板参数T
可以推导为int&
或int
,函数参数应该是int&
或者int&&
类型,它们都不是“ T&@
”(不管那种类型是什么)。所以你需要语言中的语法来指定一个声明符T&@
,它不是一种可以存在,因为它实际上总是指向一些其他类型,无论是int&
或int&&
。
至少在我们得到的语法中,类型T&&
是一个真正的类型,引用合并规则不是专用于使用通用引用的函数模板,它们与模板之外的其他类型系统完全一致:
struct A {} a;
typedef A& T;
T&& ref = a; // T&& == A&
或等同地:
struct A {} a;
typedef A& T;
std::add_rvalue_reference<T>::type ref = a; // type == A&
当T
是左值引用类型时, T&&
也是。 我不认为需要一个新的语法,规则实际上并不复杂或混乱。
为什么通用引用使用与右值引用相同的语法? 这不是一个不必要的混乱来源吗? 委员会是否考虑过其他语法...
是的,这令人困惑,IMO(我不同意@JonathanWakely在这里)。 我记得在一次非正式讨论(午餐,我认为)关于整体特征的早期设计时,我们讨论过不同的符号(Howard Hinnant和Dave Abrahams在那里提出他们的想法,而EDG家伙们正在给出关于它如何适合的反馈在核心语言中;这比N1377早)。 我想我记得&?
和&|&&
被认为是,但所有这些都是口头的; 我不知道会议记录已被采纳(但我相信这也是约翰建议使用&&
作为右值引用时)。 那些是设计的早期阶段,然而,当时有很多基本的语义问题需要考虑。 (例如,在同样的午餐讨论中,我们也提出了没有两种参考的可能性,而是有两种参考参数。)
在“类模板参数推导”(P0099R3)的C ++ 17功能中可以找到这种混淆的更近期方面。 通过转换构造函数和构造函数模板的签名来形成函数模板签名。 对于类似的东西:
template<typename T> struct S {
S(T&&);
};
一个函数模板签名
template<typename T> auto S(T&&)->S<T>;
形成用于扣除类似的声明
int i = 42;
S s = i; // Deduce S<int> or S<int&>?
推导T = int&
这将是违反直觉的。 因此,在这种情况下,我们不得不添加一个“特殊演绎规则禁用特殊演绎规则”:-(
上一篇: Syntax for universal references
下一篇: Intuitive understanding of functions taking references of references