无参数自动检测模板参数

时间:2014-06-24 15:41:28

标签: c++ c++11

这是an answer与另一个SO post的分支。

我有以下工作代码,预期输出。

#include <iostream>

template <typename T>
T twice(T in)
{
   return 2*in;
}

struct Foo
{
   Foo operator+(int (*func)(int in)) const
   {
      Foo ret{data};
      ret.data += func(ret.data);
      return ret;
   }
   int data;
};

int main()
{
   Foo f1{20};
   Foo f2 = f1 + twice;
   Foo f3 = f1 + twice<int>;
   std::cout << f2.data << std::endl;
   std::cout << f3.data << std::endl;
}

直到昨天我才知道即使没有参数,编译器也可以推断出函数模板的类型参数。在上面的代码中,表达式

f1 + twice

f1 + twice<int>

导致相同的值。

我的问题是:在C ++ 03 / C ++ 11标准中,我们可以为编译器的自动类型检测逻辑找到必要的支持文档吗?

2 个答案:

答案 0 :(得分:4)

  

C ++ 11 14.8.2.2模板参数可以从获取重载函数地址时指定的类型推导出来。

此处,参数类型operator+指定的类型为int (*)(int),重载函数为twice,因此推导出int作为模板参数匹配功能类型。如果您需要该扣除的血腥细节,请参见14.8.2.5。

答案 1 :(得分:3)

这与实际的c ++ 11标准最接近,但我发现的草案仍然是公开可用的版本:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf

我相信在您编写Foo f2 = f1 + twice;并将twice作为函数地址传递时,会完成模板参数推导。 twice作为函数的地址传递给operator+。我相信以下机制起作用:

  

14.8.2.2 使用函数模板的地址推导模板参数   [temp.deduct.funcaddr]:

     

模板参数可以从获取重载函数地址时指定的类型推导出来(13.4)。功能模板的功能类型和指定的类型用作P和A的类型,扣除按照14.8.2.5中的描述进行。

因此,实际的模板推导将基于funct的类型完成。我相信 14.8.2.5 的相关段落是 1 2

  

14.8.2.5 从类型[temp.deduct.type]中减去模板参数`:

     

1 模板参数可以在几个不同的上下文中推导出来,但在每种情况下,根据模板参数指定的类型(称为P)与实际类型进行比较(称为A并且,在替换推导出的值之后,尝试找到将产生P的模板参数值(类型参数的类型,非类型参数的值或模板参数的模板)(调用)它推导出A),与A兼容。

     

2 在某些情况下,扣除是使用一组P和A类型完成的,在其他情况下,会有一组相应的类型P和A.类型扣除是独立完成的对于每个P / A对,然后组合推导出的模板参数值。如果不能对任何P / A对进行类型推导,或者对于任何一对,推导导致一组以上可能的推导值,或者如果不同的对产生不同的推导值,或者任何模板参数仍未推断或明确推断特定的,模板   论证推论失败。

基本上,您将twice作为指向operator+的指针传递,然后通过operator+中定义的函数类型推导出模板参数。因此,您的实际类型Aint (*)(int in)P的模板类型twiceA匹配且仅int twice(int)适合。

我希望我把一切都搞定。