在模板的上下文中,以下"引用折叠"规则适用:
template <typename T>
void foo(T && t)
{
//T& & -> T&
//T& && -> T&
//T&& & -> T&
//T&& && -> T&&
}
为什么语言禁止&#34;普遍参考&#34;来自const
资格赛?
template <typename T>
void foo(T const && t)
如果类型已经解决了参考(4个案例中的3个),那似乎是有意义的。
我确信这个想法与该语言的其他一些设计方面不相容,但我无法完全看清楚。
答案 0 :(得分:4)
最初,右值参考提案表示如果P
是“右值参考类型”,则会发生转换。 However, a defect report后来注意到了
此外,请考虑这种情况:
template <class T> void f(const T&&); ... int i; f(i);
如果我们在这种情况下将
T
推断为int&
,则f(i)
会调用f<int&>(int&)
,这似乎违反直觉。我们希望调用f<int>(const int&&)
。因此,我们希望措辞澄清,14.8.2.1 [temp.deduct.call]第3段中的A&
扣除规则仅适用于T&&
而不是cv T&&
作为注意目前暗示。
似乎有一段时间段const T &&
,T
为U&
,已转换为const U&
。这被改为与另一条规则一致,即const T
T
U&
将U&
保留T
(忽略引用的cv限定符)。因此,当您将上述示例中的int&
推断为int&
时,函数参数将保持const int&
,不 f<int>(const int&&)
。
在缺陷报告中,记者表示“我们更愿意调用const int&&
”,但在缺陷报告中没有提供任何理由。我可以想象,原因在于,在不引入与其他规则不一致的情况下修复此问题似乎过于复杂。
我们还应该记住,缺陷报告是在rvalue引用仍然可以绑定到左值的时候进行的 - 即this.opendoc = function () {
var h = 500, w = 500;
var billhref = '/pages/bill.html';
var openedwidow = window.open(billhref, '', 'scrollbars=1,height='+Math.min(h, screen.availHeight)+',width='+Math.min(w, screen.availWidth)+',left='+Math.max(0, (screen.availWidth - w)/2)+',top='+Math.max(0, (screen.availHeight - h)/2));
};
可以绑定到int左值。这只是在Dave&amp; amp;道格,“RValue参考的安全问题”出现了。所以,在我看来,一个有效的演绎(当时)比一个演绎更有价值,而这个演绎只是反直觉和掉线的限定词。
答案 1 :(得分:2)
参考已经发生了这种情况;如果您的T
是U const &
,则T &&
将折叠为U const &
。术语“通用引用”确实意味着通用引用:您不需要在其中指定const
来获得常量引用。
如果你想拥有一个真正的通用引用机制,你需要你的T &&
能够成为各种引用,将各种常量。并且,T &&
就是这样做的。它折叠到所有四种情况:l值和r值引用,以及const
和非 - const
。
另一种方式解释,const
ness是类型的属性,而不是引用,即当你说T const &
时,你实际上是在谈论U &
,其中U
1}}是T const
。 &&
也是如此(尽管对const
的r值引用不太有用)。
这意味着,如果您希望将您的通用引用折叠为U const &
,只需将其传递给您想要的类型:U const &
,它就会崩溃到那个。< / p>
更直接地回答您的问题:该语言不会“禁止”在声明通用引用时使用const
。这就是说,如果你改变声明通用引用的机制甚至一点点 - 即使在const
和T
之间插入一个低&&
- 那么你就不会有一个(字面上)“普遍”的参考,因为它不会接受任何东西。
答案 2 :(得分:0)
为什么您认为该语言不允许使用const r值引用?
在下面的代码中,将要打印什么?
#include <iostream>
struct Foo
{
void bar() const &
{
std::cout << "&\n";
}
void bar() const &&
{
std::cout << "&&\n";
}
};
const Foo make() {
return Foo{};
}
int main()
{
make().bar();
}
答案:
&&
为什么呢?因为make()返回一个const对象,在这个上下文中它是一个临时对象。因此r值引用const。
答案 3 :(得分:-2)
Template argument deduction有一个特殊情况,即“rvalue引用cv-unqualified模板参数”。转发/通用引用依赖于这种非常特殊的情况。有关详细信息,请参阅链接文章中的“从函数调用中扣除”部分。
请注意,在模板参数推断之前,将删除所有顶级cv限定符;但是,引用从不具有顶级cv限定符,并且上述规则不适用,因此特殊规则也不适用。 (与指针相反,没有“const引用”,只有“引用const”)