我经常发现需要使用以下模式:
template<typename T>
class SomeClass : public Base {
SomeClass(const T& t) {...}
...
};
template<typename T>
SomeClass<T>* makeSomeClass(const T& t) {
return new SomeClass<T>(t);
}
使用它:
Base* = makeSomeClass(123);
当我不想显式指定T
因为它非常复杂(函数类型等)并且函数参数可以隐式推导出类型时,这很有用。
没有额外的“make”功能,有没有办法做到这一点?为什么模板推导仅在函数参数中起作用而在构造函数参数中不起作用?
答案 0 :(得分:3)
在构造函数参数中工作,如果构造函数本身就是模板。不同之处在于,当您使用助手时,您正在使用 function 模板,编译器可以在其中推断出类型。如果没有帮助程序,则使用类模板,编译器必须在调用(非模板)构造函数之前以某种方式推断出类型。
答案 1 :(得分:3)
不,如果没有额外的make功能,就无法做到这一点。
它不适用于构造函数的原因是因为它会非常复杂。考虑一下:
template <typename T>
struct Foo
{
Foo(const T& val) { ... }
Foo(const Foo<T>& other) { ... } // Copy constructor
};
Foo<int> x;
如果我打电话怎么办?
Foo(x);
这会给我Foo< Foo<int> >
还是我为Foo<int>
调用复制构造函数?
在太多的地方会很模糊,所以额外的功能是必要的。
请注意,您可以使用模板模板自动创建make函数:
template <template <typename> class TemplateClass, typename Type>
TemplateClass<Type> make(const Type& x)
{
return TemplateClass<Type>(x);
}
然后你可以使用:
make<SomeClass>(123); // returns a SomeClass<int>
答案 2 :(得分:0)
有没有额外功能的方法?不,没有。为什么演绎仅适用于功能?因为使用函数你实际上提供了参数。如果允许类,那么推断模板参数的唯一方法是在构造函数被调用初始化时,这会产生许多额外的规则和异常并使事情变得复杂,