【问题标题】:Why type deduced for T is const int in void func(T const &t)为什么为 T 推导的类型是 void func(T const &t) 中的 const int
【发布时间】:2017-02-23 16:22:26
【问题描述】:

我正在阅读模板中的类型推导,这是一个困扰我的问题

template<typename T>
void funt(T const &t);
int x = 10;
func(x);

T会被推导出为const intt的类型将是int const &amp; 我理解为什么t 必须是int const &amp; 的原因,因此传递给函数的x 将保持不变,因为函数接受const T&amp;。 但我看不出T 必须也是const 的原因。在我看来,将T 推断为int 不会破坏这段代码中的任何内容? 就像在另一个例子中一样:

template<typename T>
void funt(T const &t);
int const x = 10;
func(x);

这里T被推导出来只是int,而x中的const被省略了

或者我在这里遗漏了什么?

【问题讨论】:

  • “演绎”是福尔摩斯所做的。 “扣除”是当老板发现你在工作中浏览互联网时对你的薪水所做的。 “扣除”也是刹车对公共汽车速度的影响。
  • 是什么让你想到T 被推导出为const int?! Counter-example
  • 如果T 被推导出为const int,这意味着你有void funt(const const int &amp; t)T 的正确类型显然是 int 这里。将T 替换为int 并亲自查看推论是否正确。你得到void funt(int const &amp;t);
  • 无法复制。 ideone.com/aRnclc.
  • @Kerrek 我的注意力不集中让我这么想。我现在检查了这本书,我知道我哪里弄错了。顺便说一句,我可以在这里应用哪个词?扣分对吧?

标签: c++ templates type-deduction


【解决方案1】:

类型推断规则不是很简单。但作为一般经验法则,主要有 3 种类型演绎案例:

  1. f(/*const volatile*/ T&amp; arg) - 在这种情况下,编译器对参数执行类似于“模式匹配”的操作以推断类型 T。在您的第二种情况下,它与您的论点的类型完美匹配,即int const,与T const,因此T 被推断为int。如果参数缺少 CV 限定符,就像在您的第一个示例中一样,则编译器不会在模式匹配中考虑它们。所以,当你通过例如一个int xf(const T&amp; param),然后const 在模式匹配期间被丢弃,T 被推断为int,因此f 被实例化为f(const int&amp;)
  2. f(/*const volatile*/ T arg) - cv-ness (const/volatile) 和参数的引用性被忽略。因此,如果您有类似const int&amp; x = otherx; 的内容并将x 传递给template&lt;class T&gt; void f(T param),则T 被推断为int
  3. f(T&amp;&amp; arg) - T 被推断为左值引用(如int&amp;)或右值(如int),具体取决于arg 分别是左值还是右值。这种情况有点复杂,我建议阅读更多关于转发引用和引用折叠规则的内容,以了解发生了什么。

Scott Meyers 在Effective Modern C++ 书的第 1 章中详细讨论了模板类型推导。该章节实际上是在线免费的,请参阅https://www.safaribooksonline.com/library/view/effective-modern-c/9781491908419/ch01.html

【讨论】:

  • 这是我现在正在阅读的书,正如我在对我的问题的评论中所说的那样,我只是弄错了。谢谢你的回答。
  • @Vaskaelgato 将模板类型推导视为模式匹配(对于参考案例),一切都会有意义。
  • 我不想创建与同一主题相关的同一问题。估计书里有错。在 Case1 的最后,他们展示了 param 是指针还是指向 const 的指针的示例。书上说 T 是 const int,param 的类型是 const int* 但是这里的代码告诉我 T 是 int,param 的类型是 const int* ideone.com/7xsJKh
  • @Vaskaelgato 我认为这是 demangler 的问题(我相信 const 正在被 typeid 从类型中删除)。只需尝试在被调用的函数体内使用std::cout &lt;&lt; __PRETTY_FUNCTION__ &lt;&lt; std::endl;,您就会看到函数的名称以及模板类型。所以在你的情况下T = const char正如你所期望的那样,看到它直播here
  • @Vaskaelgato 所以是的,typeid(char) == typeid(const char) 对于编译器,请参阅stackoverflow.com/q/8888960/3093378。所以依靠__PRETTY_FUNCTION__来找出实际的类型。
猜你喜欢
  • 1970-01-01
  • 2012-08-02
  • 2019-06-26
  • 1970-01-01
  • 2017-10-07
  • 1970-01-01
  • 2015-02-27
  • 2016-12-12
  • 1970-01-01
相关资源
最近更新 更多