c++ 返回具有任何模板参数类型的模板化对象的函数

jhkqcmku  于 2022-12-05  发布在  其他
关注(0)|答案(3)|浏览(237)

我有一个模板类,说:

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
...
4sup72z8

4sup72z81#

如果你把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做成一个模板,只返回由条件确定的一个类型。

amrnrhlw

amrnrhlw2#

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

js81xvg6

js81xvg63#

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()

相关问题