【问题标题】:Why is reference template argument not deducing const?为什么引用模板参数不推导出 const?
【发布时间】:2016-05-24 11:28:15
【问题描述】:

我编写了以下代码,对于指针,它显示了正确的参数类型,但是当我使用引用时,它只显示 int 而没有 const。为什么?

template <typename T>
void increment(T& x)
{
    std::cout << "Argument type is : " << typeid(x).name() << std::endl;
    //x = x + 1;
}

template <typename T>
void increment(T* x)
{
    std::cout << "Argument type is : " << typeid(x).name() << std::endl;
    //x = x + 1;
}  

int main()
{
    const int x = 0;
    const int y = x;
    increment(x);
    increment(&y);
}

输出:

Argument type is : int 
Argument type is : int const *

请您解释一下为什么const 没有在参考中显示?

【问题讨论】:

  • 因为const 是限定符,而不是类型?
  • 为什么它显示指针参数的这个限定符?
  • 尝试打印:typeid(int const).name().
  • ... 并尝试打印 typeid(int const*).name() 和 typeid(int * const).name()。

标签: c++ templates reference type-deduction


【解决方案1】:
C++11 §5.2.8/4

” ... 如果 type-id 的类型是对可能有 cv 限定类型的引用,则 @ 的结果987654321@ 表达式指的是一个 std::type_info 对象,它表示 cv 的非限定引用类型。 …

C++11 §5.2.8/5

” 泛左值表达式的顶级 cv-限定符或作为 typeid 的操作数的 type-id 是总是被忽略。

本质上,任何顶级 const 都会被删除,就像正式函数参数类型 wrt 一样。生成的函数类型以及引用类型 T&amp; 中的 T 的 cv 限定符被删除。

后者可能是为了不区分 T&amp; 和 T - 它们产生相同的结果。

【讨论】:

  • 所以基本上在这种情况下,const drop 是两个步骤的过程。
  • @Nawaz:我认为最简单的概念模型和规则旨在建模的是两步转换,是的。删除 reference-to,然后删除该结果的任何 cv 限定。但正式手头的案例只是一步,通过 §5.2.8/4。
【解决方案2】:

来自typeid reference:

如果 type 是引用类型,则结果引用代表被引用类型的 std::type_info 对象。

和

在所有情况下,typeid 都会忽略 cv 限定符(即typeid(T)==typeid(const T))

(更准确地说是顶级const)T当然被推导出为const int。


标准段落为[expr.typeid]/4和[expr.typeid]/5

【讨论】:

  • 那么有什么方法可以知道 T 被推导出为 const int
  • @Kapil 因为那不是顶级const。您可以使用 std::is_const 特征检查 const-ness。
  • @Kapil 检查类型使用 Scott Mayers 技巧:template&lt;typename T&gt; struct TD; TD&lt;T&gt; ii; 或 template&lt;typename T&gt; struct TD; TD&lt;decltype(variable)&gt; ii; 此生成的编译错误还包含 T 类型或 variable 的确切类型
  • @Kapil,有很多方法可以知道 T 是否被推导出为 const int,而不是 typeid
猜你喜欢
  • 1970-01-01
  • 2018-12-09
  • 1970-01-01
  • 2015-10-06
  • 2011-08-28
  • 1970-01-01
  • 2012-08-09
  • 1970-01-01
相关资源
最近更新 更多