【问题标题】:Template deduction interesting case, c++模板推演趣味案例,c++
【发布时间】:2015-07-08 12:16:21
【问题描述】:

考虑一下代码的这种平静:

template<class T>
void f(const T& t)
{
    static int x = 0;
    cout<<++x<<endl;
}

int main()
{
    int j = 0;
    const int i = 0;
    f(5);
    f(i);
    f(j);
}

我已经为 3 种类型调用了该函数。虽然5和j可以是同一个东西,只是int,const int i肯定是不同的类型。
但无论如何我的输出是:

1
2
3

这意味着编译器为不同类型实例化相同的函数。
我对么?谁能解释一下为什么?

【问题讨论】:

  • 因为模板就是这样工作的! :-)
  • 通过cout &lt;&lt; &amp;x &lt;&lt; endl; 打印x 的地址可能是一种更简单的方法来识别正在调用的对象。最好的是cout &lt;&lt; __PRETTY_FUNCTION__ &lt;&lt; endl;,但不能保证在所有编译器中都有。

标签: c++ templates instantiation type-deduction


【解决方案1】:

来自[temp.deduct.call]:

模板参数推导是通过比较每个函数模板参数类型(称为 P)与 调用的相应参数的类型(称为 A),如下所述。

Pconst T&amp;A 在三个调用中是 intintconst int

然后我们有:

如果P是引用类型,则P引用的类型用于类型推导。

P 是引用类型,所以我们使用P' == const TA == intA == const int 进行推导。在这两种情况下,我们都推导出T == int,因此P' == const int(和P == const int&amp;)和推导出的A == const int。对于前两个调用,这比原来的 A 更符合 cv-qualified 条件,但这是明确的:

一般来说,推导过程试图找到模板参数值,使推导的 A 与 A 相同(在如上所述转换类型 A 之后)。但是,有三种情况允许 不同之处:
— 如果原始 P 是引用类型,则推导出的 A(即引用所指的类型)可以是 比转换后的 A 更符合 cv 要求。

因此,所有三个案例都只是调用f&lt;int&gt;

【讨论】:

  • 我认为在这两句话之间插入 otherwise 可能只是一个编辑问题;也许提交一个github问题?
  • @dyp 我真的不知道该怎么做
  • 通过github.com/cplusplus/draft/issues 。右上角有一个绿色的“新问题”按钮,可能只有你有一个 github 帐户(并且已登录)。相关部分在这里:github.com/cplusplus/draft/blob/master/source/…
  • @dyp 再想一想,你肯定是对的。 template &lt;typename T&gt; void foo(T&amp; ) 不能在 A 上删除顶级 cv 限定符。所以不可能有那种递归。不过我不确定有更好的表达方式,所以我不知道我会提出什么建议。
  • 好吧,我想像 如果P 是一个 cv 限定类型,则 P 类型的顶级 cv 限定符将被忽略以进行类型推导;否则,如果P 是引用类型,则使用P 引用的类型进行类型推导。 或者将这两个句子颠倒过来可能会更好,这样更明显的是引用类型不是简历合格。
【解决方案2】:

这里f 将被实例化一次,类型为int,因为所有3 个调用都只调用f&lt;int&gt;

【讨论】:

  • 可能想解释一下为什么ij 是一样的
  • 最好的问题可能是“为什么使用jT 不是const int?”。
【解决方案3】:

只要类型推导有效就是正确的。

考虑一下:

#include <iostream>

template<class T>
void f(const T& t)
{
    static int x = 0;
    std::cout<< "x=" << ++x<<std::endl;
}

template<class T>
void f(T&& t)
{
    static int y = 0;
    std::cout<< "y=" << ++y<<std::endl;
}

template<class T>
void f(T& t)
{
    static int z = 0;
    std::cout<< "z=" << ++z<<std::endl;
}

int main()
{
    int j = 0;
    const int i = 0;
    f(5);
    f(i);
    f(j);
}

输出:

y=1
x=1
z=1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多