为什么构造函数不能推导出模板参数?

Gre*_*bur 58 c++

template< class T >
class Foo {
public:
  Foo( T t ) { }
};

int main () {
  int i = 0;
  Foo f( i );
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,编译器抱怨在'f'之前缺少模板参数.我理解从构造函数的参数中推导出类的模板参数不是标准的一部分,但我的问题是为什么?编译器是否具有隐式实例化Foo<int>和调用其构造函数所需的所有信息?

编辑要清楚的是我打电话与构造int(而不是一个short,long,void*,等)

Seb*_*edl 35

因为没有人说明究竟是如何运作的.目前向标准委员会提出了使其有效的建议.它还列出了一些困难:

http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4471.html

更新:这是该提案的最新版本:

http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0091r0.html

  • 从答案本身的链接文章中总结一些困难可能是个好主意.虽然不是一个仅限链接的答案,但如果链接死亡,这将失去很多价值. (11认同)

Ben*_*igt 18

TL; DR:模板专业化


它们可以,但只有函数本身的模板参数,而不是类型.

声明Foo f(0);是非法的,因为没有命名的类型Foo.也许你在考虑

auto f = Foo(0);
Run Code Online (Sandbox Code Playgroud)

但这也是不允许的,因为编译器不知道要搜索的范围(有无限的潜在类型,带有命名的构造函数,Foo并且具有特化,可能不止一个带有构造函数Foo(int))

通常的方法是使用工厂辅助函数:

auto f = make_foo(0);
Run Code Online (Sandbox Code Playgroud)

工厂函数的返回类型取决于其参数的类型推导.


您可以想象工厂函数可以在命名空间范围内自动生成,然后应用通常的函数重载规则,但这会遇到很大的困难,因为类型和构造函数本身都可以有模板参数.这些可以简单地连接起来,但是这会限制使用可变参数列表的类模板,因为没有办法区分类型参数的结束和函数参数的开始.


0x4*_*2D2 8

Foo是一个类模板,而不是一个类.它的类型总是需要以某种方式提供,以便使用正确的类型生成类.你不能这样做,Foo因为Foo它不是一种类型,而是一种类型Foo<int>.它创建了一个这样的类:

class Foo {
public:
  Foo( int t ) { }
};
Run Code Online (Sandbox Code Playgroud)

如果您只提供Foo,编译器将不知道如何生成类.Foo<int> f(0)因为Foo<int>生成类而替换Tint.根据您调用构造函数的类型,编译器已经知道构造函数正在接受int.


Dav*_*d K 5

要实例化的类的名称是 Foo<int>(如您所示).

也可以写Foo<short> f(0),或Foo<unsigned long> f(0),或Foo<Foo<double>*> f(0).但是,在这些情况下,如果只编写,则不希望编译器能够猜出类型Foo f(0).

可以想象,C++ 可以用规则来指定以某种方式进行一些这样的猜测(例如,文字0意味着类型参数int而不是其他方式),但是语言将比现在更加复杂并且会有是人们编程编程错误的其他方法.实际上在这样的声明中写下你的意思似乎并不是太多问题.

编辑:张贴在此之后,我注意到在另一个答案,有 使C++这样的功能的建议,确如人们可以想象.