我无法在非模板类中的专用模板类中调用方法。
我有一个类似下面的模板类:
template<class T>
class Builder{
Builder() { t = new T; }
Builder &setName(const int &name);
// other methods
T &build();
protected:
T *t;
}
template<class T>
T &Builder<T>::build() {
return *t;
}
// other implementations
而且我有一个从专门的模板类继承的类
class SomeClass;
//template<class T>
class SomeClassBuilder : public Builder<SomeClass> {
public:
SomeClassBuilder() : Builder<SomeClass>() {}
SomeClassBuilder &setAge(int age);
}
class SomeClass{
public:
static SomeClassBuilder createExperiment(){
return {};
}
// other methods
}
但是,当我尝试使用此SomeClassBuilder时,具体取决于我如何链接方法调用,有时会出错。下面的代码段给出了错误(has no member named setAge
)。
SomeClass::Engine()
.setName("Name")
.setAge(109)
.build();
像下面那样束缚方法调用不会出错,因为setAge
类的SomeClass
方法位于那些模板类之前。
SomeClass::Engine()
.setAge(109)
.setName("Name")
.build();
您的问题是,引用SomeClassBuilder &
可以解释为Builder<SomeClass> &
,但反之则不行(为此您需要动态转换)。由于Builder<T>
的方法返回Builder<T> &
,因此实际上没有set_age
成员。这对模板没有问题,但对继承没有问题。
我看到3种解决方案:
set_age
,而应用该功能的类型仍然是SomeClassBuilder &
。SomeClassBuilder
中的所有函数,以使它们执行基类中的方法,然后将*this
返回为SomeClassBuilder &
。class Child
添加到基类,该类获得继承的Child的类型,并让所有方法返回Child &
而不是Builder &
,而您必须dynamic_cast
[ C0]之后再返回。然后,this
应该继承自SomeClassBuilder
(需要向前声明)。也:不要使用原始指针来拥有内存。代码中的原始Builder<T, SomeClassBuilder>
不是一个好兆头。请改用new
。
std::unique_ptr
返回Builder<SomeClass>::setName
,它肯定没有任何Builder<SomeClass>
方法。首先调用setAge()
时,您返回setAge()
,并且它确实具有此方法,因此,此行为正是编译器所期望的。
要解决此问题,您可以尝试使用SomeClassBuilder
返回实际的CRTP。
基本上,您的构建器定义将更改为
SomeClassBuilder
并且,对于template <typename T, typename Derived>
class Builder
{
//...
Derived& setName();
//...
};
:
SomeClassBuilder
如果您想坚持自己的设计方式,我认为除了使用class SomeClassBuilder: public Builder<T, SomeClassBuilder> { ... }
之外别无选择。
更明确地说,这是一个可行的示例,可能会对您有所帮助:
CRTP