10

在模板的上下文中,应用了以下“引用折叠”规则:

template <typename T>
void foo(T && t)
{
    //T&  &   -> T&
    //T&  &&  -> T&
    //T&& &   -> T&
    //T&& &&  -> T&&
}

为什么该语言禁止“通用引用”具有const限定词?

template <typename T>
void foo(T const && t)

如果类型已解析为引用(4 个案例中的 3 个),这似乎是有道理的。

我确信这个想法与该语言的其他一些设计方面不兼容,但我不能完全看到完整的画面。

4

4 回答 4

4

最初,右值引用提案说,如果P是“右值引用类型”,就会发生转换。然而,后来发现了一份缺陷报告

此外,考虑这种情况:

template <class T> void f(const T&&);
...
int i;
f(i);

如果我们在这种情况下推断Tthenint&调用f(i)f<int&>(int&)这似乎违反直觉。我们更喜欢这样f<int>(const int&&)称呼。因此,我们希望澄清措辞,A&即 14.8.2.1 [temp.deduct.call] 第 3 段中的扣除规则仅适用于表格T&&,而不适用cv T&&于注释当前所暗示的。

似乎有一段时间const T &&,随着T存在U&,被转变为const U&。这已更改为与另一条规则一致,即const T, where TisU&将保留U&(忽略引用上的 cv 限定符)。因此,当您T在上面的示例中推断为int&时,函数参数将保留int&而不是 const int&

在缺陷报告中,报告者声明“我们更喜欢f<int>(const int&&)被称为”,但在缺陷报告中没有提供任何理由。我可以想象,原因是在不引入与其他规则不一致的情况下解决这个问题似乎太复杂了。

我们还应该记住,缺陷报告是在右值引用仍然可以绑定到左值的时候进行的——即const int&&可以绑定到一个 int 左值。直到后来,当 Dave & Doug 的一篇论文“RValue References 的安全问题”出现时,这才被禁止。所以,在我看来,一个有效的推论(当时)比一个简单地违反直觉和放弃限定词的推论更有价值。

于 2016-09-03T13:06:17.537 回答
2

参考文献确实已经发生了这种情况;如果你T是一个U const &,那么T &&就会崩溃到U const &。术语“通用参考”确实意味着通用参考:您无需const在其中指定以获得恒定参考。

如果你想拥有一个真正通用的引用机制,你需要你T &&能够成为各种引用,将各种常量。而且,T &&正是这样做的。它折叠到所有四种情况:l 值和 r 值引用,以及两者const和非const.

换一种方式解释,constness 是类型的属性,而不是引用,即当您说 时T const &,您实际上是在谈论 a U &, where Uis T const。对于&&(尽管对 a 的 r 值引用const不太有用)也是如此。

这意味着,如果您希望您的通用引用折叠到 a U const &,只需将您想要的类型的东西传递给它: a U const &,它就会完全折叠到那个。

更直接地回答您的问题:该语言本身并不“禁止”在const通用参考声明中使用。这就是说,如果你稍微改变声明通用引用的机制——即使在 the和 theconst之间插入一个低级——那么你将不再有(字面上的)“通用”引用,因为它不会t接受任何东西。T&&

于 2016-09-03T06:05:14.223 回答
0

为什么您认为该语言不允许 const r-value 引用?

在下面的代码中,将打印什么?

#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。

于 2016-09-03T06:35:10.997 回答
-2

模板参数推导对于“对 cv 非限定模板参数的右值引用”有一种特殊情况。转发/通用引用所依赖的正是这种非常特殊的情况。有关详细信息,请参阅链接文章中的“从函数调用中推导”部分。

请注意,在模板参数推导之前,所有顶级 cv 限定符都被删除;但是,引用永远不会有顶级 cv 限定符,并且上述规则不适用,因此特殊规则也不适用。(与指针相比,没有“const 引用”,只有“对 const 的引用”)

于 2016-09-03T06:23:58.023 回答