【问题标题】:C++ - inherit from base class with member function as template argumentC++ - 从基类继承,成员函数作为模板参数
【发布时间】:2019-05-05 17:14:35
【问题描述】:

我有一个使用 CRTP 的非常简单的类:

template <typename DerivedType, void (DerivedType::*updateMethod)() = &DerivedType::update>
class UpdatableBase {};

class MyClass : private UpdatableBase<MyClass> {
public:
    void update() {
    }
};

int main() {
    return 0;
}

当使用g++ test.cpp -std=c++14 编译时,会给出:

test.cpp:2:85: error: no member named 'update' in 'MyClass'
template <typename DerivedType, void (DerivedType::*updateMethod)() = &DerivedType::update>
                                                                       ~~~~~~~~~~~~~^
test.cpp:5:25: note: in instantiation of default argument for 'UpdatableBase<MyClass>' required here
class MyClass : private UpdatableBase<MyClass> {
                        ^~~~~~~~~~~~~~~~~~~~~~
1 error generated.

为什么会说“‘MyClass’中没有名为‘update’的成员”?很明显。

【问题讨论】:

  • 好吧,在您的模板实例化时MyClass 是不完整的,并且它没有update 方法...根据您想要完成的内容,您可能需要一些间接性。
  • 好的。有没有办法我可以接受一个方法作为参数,同时仍然具有默认值?

标签: c++ c++14 crtp


【解决方案1】:

这是 CRTP 的一个非常常见的问题:编译器在读取派生类定义之前先实例化基类定义。

解决方法是只在基类成员定义中使用派生类的定义

#include <type_traits>

template <typename DerivedType, class DelayedParameter = void>
class UpdatableBase {
   public:
   //definition of members of templates are instantiated when needed!
   void update(){
      if constexpr(std::is_same_v<DelayedParameter,void>)
        static_cast<DerivedType>(this)->update();
      else
        (static_cast<DerivedType*>(this)->*DelayedParameter::value)();
     }
  };

class MyClassDelayedParameter;

class MyClass:public UpdatableBase<MyClass,MyClassDelayedParameter> 
  //the compiler only instantiate the definition of the base class:
  //it will only instantiate the DECLARATION of the base class members.
  {
  public:
    void update();
  };

//Here MyClass is defined so we can access its member.
struct MyClassDelayedParameter:
  std::integral_constant<void(MyClass::*)(),&MyClass::update>
  {};

//UpdatableBase<...>::update DEFINITION is instantiated here. At this point
//of instantiation, MyClass and MyClassDelayedParameter are defined.
int main() {
    MyClass a;
    UpdatableBase<MyClass,MyClassDelayedParameter>& b=a;
    b.update();
    return 0;
}

DEMO

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-13
    • 1970-01-01
    • 2014-07-15
    • 1970-01-01
    • 2013-03-25
    相关资源
    最近更新 更多