返回具有任意模板实参类型的模板化对象的函数



我有一个模板化的类,比如:

template <class C, int I>
class A {
A() {};
someMethod(){...};
};
现在,假设我在代码中使用了这个类的几个对象,它们具有不同的模板参数(类B、C和D是一些已定义的类):
A<B, 1> object1;
A<C, 2> object2;
A<D, 3> object3;

我想要的是一个基于某些逻辑返回以下三个对象之一的函数:

A getObject(){
if(condition1)
return object1;
else if(condition2)
return object2;
else
return object3;
}

然而,当我试图编译这个,我得到error: invalid use of template-name ‘A’ without an argument list,这是有意义的,但我不知道我应该提供哪些参数?例如,如果我输入

A<B, 1> getObject(){
return object1;       
}

则只能返回object1,而不能返回object2object3

最终,我的目标是有这样的东西:

A obj = getObject();
...
lot's of code where obj.someMethod() get's called a lot
...

如果你把A<B,1>A<B,2>A<B,3>看作是三个完全不相关的类FooBarMoo,这就更容易理解了。现在试着找到一种方法从一个方法返回那些:你需要一个共同的基础或anyvariant…运行时多态性:同样的方法返回一个对象,只要它实现了一个接口,你就不用关心它的类型。

class A_base {
virtual void someMethod() = 0;
virtual ~A() {}
};
template <class C, int I>
class A : public A_base {
A() {}
void someMethod() override {/*...*/}
};
std::unique_ptr<A_base> getObject() {
//...
}

我假设condition只在运行时已知。否则,整个问题就没有意义了,因为如果在编译时知道它,那么您可以简单地将getObject设置为只返回由条件确定的一种类型的模板。

getObject函数上的返回语句都有不同的类型(用不同类实例化的模板有不同的类型)。函数只能返回单一类型,因此不可能原样返回模板。因此,解决方案需要所有模板共享一个公共类型。要做到这一点,您需要创建一个带有虚拟的someemethod调用的基类,使每个模板从实现了someemethod的基类继承,并从getObject函数返回一个指向基类的指针(注意不要缩小返回的派生类)。然后,您可以利用虚拟调度来调用适当的someemethod。

A不是类型,因此不能将其声明为返回值。A<B, 1>,A<C, 2>A<D, 3>都是不同的类型。但是,不需要更改A的方法是使用该对象调用函数对象,而不是返回它。你的函数将变成

template <typename F>
void getObject(int i, F f) {
if (i == 1) {
f(object1);
} else if (i == 2) {
f(object2);
} else if (i == 3) {
f(object3);
}
}

,你可以用

getObject(3, [](auto x) {
std::cout << "Call someMethod: " << x.someMethod() << std::endl;
});

在函数参数列表中包含auto x仅在最新的c++版本中可用。如果你的c++版本不支持,你就必须声明一个类,并为这些类型实现operator()

最新更新