继承模板方法
Inheriting template methods
我有一个类似于下面的类:
class SomeClass
{
public:
template<typename... Args>
void doSomething(Args && ... args);
//... other methods etc.
};
然而,我真正想要的是有两种不同的SomeClass
。理想情况下,我将能够从通用接口派生出SomeOtherClass
,但我需要doSomething
的不同实现和模板方法不能是虚拟的。我可以创建一个模板化的类,但这样一来,每个采用这些方法之一(有很多)的方法本身就必须是模板等。
我能想到的最好的方法是在基类中实现两种类型的doSomething
,并让该方法调用一个虚拟方法来确定在运行时使用哪个。
有更好的解决方案吗?
进一步解释我有很多类似的方法:
void foo(SomeClass * obj);
foo
调用obj->doSomething
,这一切都很好,但我已经意识到,我需要一种不同的SomeClass
,但希望它与这些相同的方法工作,例如:
class SomeClass
{
public:
// This won't work
template<typename... Args>
virtual void doSomething(Args && ... args) = 0;
// ... other common methods
};
class TheFirstType
{
public:
template<typename... Args>
void doSomething(Args && ... args);
// ... other specific methods
};
class TheSecondType
{
public:
template<typename... Args>
void doSomething(Args && ... args);
// ... other specific methods
};
如果合法的话,上面的是理想的,但是虚方法不能被模板化。到目前为止,我已经绕过了这个限制,只在基类中定义了doSomething
,但TheFirstType
和TheSecondType
的实现都由一个if语句分隔,该语句检查实例实际是什么类型:
template<typename... Args>
void SomeClass::doSomething(Args && ... args)
{
if (this->type() == FIRST_TYPE) {
// ... the implementation that should rightfully be part of TheFirstType
} else if (this->type() == SECOND_TYPE) {
// ... the implementation that should be part of TheSecondType
}
}
这看起来很乱,但是,所以我想知道是否有更好的方法。
我认为@stijn的答案是正确的;你有一个理想的CRTP案例。你可以选择据此改变你的逻辑。
template<class T>
class SomeClass
{
public:
template<typename... Args>
void doSomething(Args && ... args)
{
static_cast<T*>(this)->doSomething(...);
}
//other method can be virtual
virtual void foo ()
{
doSomething(...);
// ... other code;
}
};
现在只需将这些class
继承到您的其他子类:
class TheFirstType : SomeClass<TheFirstType>
{
public:
template<typename... Args>
void doSomething(Args && ... args) { ... }
virtual void foo ()
{
}
}; // do same for TheSecondType.
我猜你是在CRTP之后(尽管我不能确定,正如iammilind在评论中指出的那样):
template< class Parent >
class SomeClassBase : public Parent
{
public:
//common methods go here
};
class SomeClass : public SomeClassBase< SomeClass >
{
public:
template<typename... Args>
void doSomething(Args && ... args);
};
class SomeOtherClass : public SomeClassBase< SomeOtherClass >
{
public:
template<typename... Args>
void doSomething(Args && ... args);
};
在这种情况下可能有用的是在包装器类SomeClass
中使用宏函数。宏的好处是文本替换。通常情况下,我们不能在c++中将函数的所有参数都作为对象传递(至少在c++ 11之前,我不确定)。然而,使用宏,我们可以传递几乎任何类型的文本。这里的额外好处是,它将为每个具有此模板虚拟冲突的函数删除if/else的重复代码。
我们可以这样设置宏:
#define CLASS_SELECT(func)
do {
if (this->type() == FIRST_TYPE) {
theFirstType.func;
} else if (this->type() == SECOND_TYPE) {
theSecondType.func;
}
} while (0)
如果您不熟悉do while封装,请查看这里。该类将使用如下宏:
class SomeClass
{
TheFirstType theFirstType;
TheSecondType theSecondType;
public:
template<typename... Args>
void doSomething(Args && ... args)
{
CLASS_SELECT(doSomething (&args...) );
}
};
在上面的例子中,我实例化了SomeClass
内部的专门化对象。我不确定这是否是您喜欢的设计,如果不是,我会考虑在宏中使用静态getter函数或类似的函数。
无论如何,我承认我的解决方案可能不是理想的,但它是最好的我有到目前为止(我有同样的问题,你在我的代码)。我承认在其他答案中引用的CRTP非常酷,尽管它不适合我的需要(必须在参数中指定模板也不适合我,特别是在运行时)。
- 从具有默认值的部分指定模板类继承时发生SWIG错误,具有不带默认值的正向声明
- 将成员函数指针作为参数传递给模板方法
- 模板方法访问正向声明的类仅在没有此指针的情况下无法编译
- C++模板类继承自身
- C++11:模板方法的模板函数调用无法编译?
- 如何从ECS中的模板方法获取组件?
- 使用 SFINAE 设计模板方法
- C++模板类 - 继承调用错误的函数
- 一个模板方法,用于同时接受常量和非常量参数
- 如何解决此问题(基础模板和继承)
- C++模板方法中的循环依赖关系
- 在 C++ 中使用模板方法重写类方法
- 类中的模板方法
- 当可变参数模板类继承自模板参数时,在调用基类型的方法时扩展参数包
- 与其他模板方法继承 C++ 模板类
- 对继承的模板方法的不明确调用
- 从基类的静态模板方法中调用继承类的受保护 ctor 失败
- 模板、继承和虚拟方法 (C++)
- 继承模板方法
- 通过多级继承从模板子类调用基类的模板方法