从非模板类中调用专用模板方法

问题描述 投票:2回答:3

我无法在非模板类中的专用模板类中调用方法。

我有一个类似下面的模板类:

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();
c++ builder
3个回答
1
投票

您的问题是,引用SomeClassBuilder &可以解释为Builder<SomeClass> &,但反之则不行(为此您需要动态转换)。由于Builder<T>的方法返回Builder<T> &,因此实际上没有set_age成员。这对模板没有问题,但对继承没有问题。

我看到3种解决方案:

  1. 始终先使用set_age,而应用该功能的类型仍然是SomeClassBuilder &
  2. 覆盖SomeClassBuilder中的所有函数,以使它们执行基类中的方法,然后将*this返回为SomeClassBuilder &
  3. [使用CRTP,因此将模板参数class Child添加到基类,该类获得继承的Child的类型,并让所有方法返回Child &而不是Builder &,而您必须dynamic_cast [ C0]之后再返回。然后,this应该继承自SomeClassBuilder(需要向前声明)。

也:不要使用原始指针来拥有内存。代码中的原始Builder<T, SomeClassBuilder>不是一个好兆头。请改用new


1
投票

std::unique_ptr返回Builder<SomeClass>::setName,它肯定没有任何Builder<SomeClass>方法。首先调用setAge()时,您返回setAge(),并且它确实具有此方法,因此,此行为正是编译器所期望的。

要解决此问题,您可以尝试使用SomeClassBuilder返回实际的CRTP

基本上,您的构建器定义将更改为

SomeClassBuilder

并且,对于template <typename T, typename Derived> class Builder { //... Derived& setName(); //... };

SomeClassBuilder

0
投票

如果您想坚持自己的设计方式,我认为除了使用class SomeClassBuilder: public Builder<T, SomeClassBuilder> { ... } 之外别无选择。

更明确地说,这是一个可行的示例,可能会对您有所帮助:

CRTP
© www.soinside.com 2019 - 2024. All rights reserved.