如何在C++中编写可内联的相互抽象代码?

Łuk*_*Lew 1 c++ abstraction inline class

示例第一:

template <class HashingSolution> 
struct State : public HashingSolution {

  void Update(int idx, int val) {
    UpdateHash(idx, val);
  }

  int GetState(int idx) {
    return ...;
  }
};

struct DummyHashingSolution {
  void UpdateHash(int idx, int val) {}
  void RecalcHash() {}
};

struct MyHashingSolution {
  void UpdateHash(int idx, int val) {
    ...
  }

  void RecalcHash() {
    ...
    UpdateHash(idx, GetState(idx)); // Problem: no acces to GetState function, can't do recursive application of templates
    ...
  }
};
Run Code Online (Sandbox Code Playgroud)

在这个例子中,我可以将MyHashingSolution传递给State类,因此State可以访问HashingSolution的方法,但是HashingSolution不能调用GetState.有可能解决这个问题吗?

这是最深的循环.这里的虚拟功能使性能下降超过25%.内联对我来说至关重要.

j_r*_*ker 5

正如jalf在评论中建议的那样,您可能想要使用奇怪的重复模板模式(CRTP)的变体.也就是说,创建MyHashingSolution一个由派生类参数化的类模板:

template <typename D>
struct MyHashingSolution {
    typedef D Derived;

    void UpdateHash(int idx, int val) {
        ...
    }

    void RecalcHash() {
        ...
        UpdateHash(idx, derived().GetState(idx));
        ...
    }

private:
    // Just for convenience
    Derived& derived() { return *static_cast<Derived*>(this); }
};
Run Code Online (Sandbox Code Playgroud)

在这种情况下,因为您希望派生State类也是一个模板,所以您需要采取稍微不同寻常的步骤来声明State为采用模板模板参数的类模板:

template <template <class T> class HashingSolution>
struct State : public HashingSolution<State<HashingSolution> > {
typedef HashingSolution<State<HashingSolution> > Parent;

    void Update(int idx, int val) {
        Parent::UpdateHash(idx, val);   // g++ requires "Parent::"
    }

    int GetState(int idx) {
        return ...;
    }
};
Run Code Online (Sandbox Code Playgroud)

关键点在于,如果State继承自HashingSolution<State<HashingSolution> >,Derived则是一个派生类,HashingSolution<State<HashingSolution> >因此编译中的static_cast<Derived*>(this)向下转换HashingSolution<State>::derived()并正常工作.(如果你陷入困境并从中派生State出来HashingSolution<SomeOtherType>,然后尝试一些涉及调用的东西,derived()编译器会因为static_cast<>不符合要求而抱怨.)

然后声明State要使用的具体类,如下所示:

typedef State<MyHashingSolution> MyState;
Run Code Online (Sandbox Code Playgroud)

遗憾的是,此解决方案具有副作用,您需要将DummyHashingSolution(以及任何其他此类类型)更改为忽略其一个模板参数的模板,以使其可用作模板模板参数.