我有一个类似于下面的类:
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
}
}然而,这看起来很混乱,所以我想知道是否有更好的方法。
发布于 2011-07-16 11:33:31
我认为@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.你的任务完成了。
发布于 2011-07-15 16:18:23
我的猜测是你在追求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);
};发布于 2018-06-01 06:24:41
在这种情况下,在包装器类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封装,可以使用look here。该类将使用宏,如下所示:
class SomeClass
{
TheFirstType theFirstType;
TheSecondType theSecondType;
public:
template<typename... Args>
void doSomething(Args && ... args)
{
CLASS_SELECT(doSomething (&args...) );
}
};在上面的示例中,我实例化了SomeClass中的专门化对象。我不确定这是否是您喜欢的设计,如果不是,我会考虑在宏中使用静态getter函数或类似函数。
无论如何,我承认我的解决方案可能并不理想,但这是迄今为止我得到的最好的解决方案(我在我的代码中遇到了与您相同的问题)。我承认在其他答案中引用的CRTP非常酷,尽管它不符合我的需求(必须在参数中指定模板也不适合我,特别是在运行时)。
https://stackoverflow.com/questions/6703199
复制相似问题