以下代码在Xcode中生成编译错误:
template <typename T>
struct Foo
{
Foo(T Value)
{
}
};
int main()
{
Foo MyFoo(123);
return 0;
}
error: missing template arguments before 'MyFoo'
将Foo MyFoo(123);
更改为Foo<int> MyFoo(123);
可以解决问题,但编译器是否应该找不到合适的数据类型?
这是编译器错误,还是我误解了隐式模板参数?
答案 0 :(得分:11)
理论上,构造函数可以推断它正在构造的对象的类型,但声明:
Foo MyFoo(123);
为MyFoo
分配临时空间,并且必须知道MyFoo
的完全限定类型才能知道需要多少空间。
如果您想避免键入(即用手指)特定复杂模板的名称,请考虑使用typedef
:
typedef std::map<int, std::string> StringMap;
或者在C ++ 0x中,您可以使用auto
关键字让编译器使用类型推断 - 尽管许多人认为这会导致代码性能降低,容易出错,我自己就是这样。 ; P
答案 1 :(得分:7)
编译器只能为模板化函数计算模板参数类型,而不能用于类/结构
答案 2 :(得分:2)
这不是一个错误,它是不存在的功能。您必须在实例化期间完全指定类/结构模板参数,始终不会推断类型,因为它们可以用于函数模板。
答案 3 :(得分:2)
编译器可以推导出模板参数这样的情况:
template<typename T>
void fun(T param)
{
//code...
}
fun(100); //T is deduced as int;
fun(100.0); //T is deduced as double
fun(100.0f); //T is deduced as float
Foo<int> foo(100);
fun(foo); //T is deduced as Foo<int>;
Foo<char> bar('A');
fun(bar); //T is deduced as Foo<char>;
实际上模板参数演绎是一个很大的话题。在ACCU阅读这篇文章:
答案 4 :(得分:2)
在C ++ 11中,您可以使用decltype
:
int myint = 123;
Foo<decltype(myint)> MyFoo(myint);
答案 5 :(得分:1)
您正在尝试执行的操作现在可以在C ++ 17中使用。可以在C ++ 17中推断模板参数。
template <typename T>
struct Foo
{
Foo(T Value)
{
}
};
int main()
{
Foo a(123);
Foo b = 123;
Foo c {123};
return 0;
}
答案 6 :(得分:0)
很有意义就是这样,因为Foo不是一个类,只有Foo<T>
,其中T是一个类型。
在C ++ 0x中你可以使用auto,你可以创建一个函数让你成为Foo,让我们称之为foo(小写f)。然后你会做
template<typename T> Foo<T> foo(int x)
{
return Foo<T>(x);
}
auto myFoo = foo(55);