简体   繁体   English

我可以使用模板成员函数来替代 CRTP 以实现静态多态吗?

[英]Can I use template member functions as an alternative to the CRTP in order to implement static polymorphism?

I want to implement the template method pattern using static polymorphism in C++.我想在 C++ 中使用静态多态来实现模板方法模式。

Right now I have two classes A and B which are very similar.现在我有两个非常相似的类AB They have an identical public API and the exact same list of private data members.它们具有相同的公共 API 和完全相同的私有数据成员列表。 Most of the public member functions are also implemented identically but for some of them the two classes differ slightly in their implementation.大多数公共成员函数的实现也相同,但对于其中一些,这两个类的实现略有不同。

The situation looks somewhat like this:情况看起来有点像这样:

class A {
public:
  /* Ctor etc... */
  int One() const;
  int Two() const;
  int Three() const; /* Calls PrivateA() internally */
private:
  int PrivateA() const;
  int a;
  int b;
  int c;
};

class B {
public:
  /* Ctor etc... */
  int One() const; /* Identical to A::One() */
  int Two() const; /* Identical to A::Two() */
  int Three() const; /* Same as in A::Three() but calls PrivateB() instead of PrivateA() internally */
private:
  int PrivateB() const; /* Specific for B */
  /* Identical data members (type and semantics) to A */
  int a;
  int b;
  int c;
};

I now want to reduce code duplication by moving all the shared code and data members to a base class and delegate to sub-class specific member functions from within the base class'.我现在想通过将所有共享代码和数据成员移动到基类并从基类内部委托子类特定成员函数来减少代码重复。 That is, something like this:也就是说,像这样:

class Base {
public:
  int One() const;
  int Two() const;
  int Three() const; /* Should delegate to Private() internally */
private:
  int a;
  int b;
  int c;
};

class A : public Base {
private:
  int Private() const;
};

class B : public Base {
private:
  int Private() const;
};

I know I can solve this using the CRTP in a manner similar to this:我知道我可以以类似于以下的方式使用CRTP解决这个问题:

template<typename T>
class Base {
public:
  int One() const;
  int Two() const;
  int Three() const; /* Should delegate to Private() internally */
private:
  int a;
  int b;
  int c;
};

class A : public Base<A> {
private:
  friend class Base<A>;
  int Private() const;
  int p;
};

class B : public Base<B> {
private:
  friend class Base<B>
  int Private() const;
  int q;
};

template<typename T>
int Base<T>::Three() const {
  return static_cast<const T*>(this)->Private();
}

int A::Private() const { return this->p; }
int B::Private() const { return this->q; }

int main() {
  A a{};
  B b{};

  /* Uses shared code from base class */
  a.One();
  b.One();

  /* Base class code statically dispatches to sub-class code via CRTP */
  a.Three(); /* Returns value of p */
  b.Three(); /* Returns value of q */

  return 0;
}

Now onto my question.现在开始我的问题。

Is it possible to achieve the same result without making Base a template class?是否可以在使Base成为模板类的情况下获得相同的结果? Can I accomplish the same thing using eg template member functions?我可以使用例如模板成员函数来完成同样的事情吗?

/* Note: no template */
class Base {
public:
  int One() const;
  int Two() const;

  template<typename T>
  int Three() const; /* Should delegate to Private() internally */
private:
  int a;
  int b;
  int c;
};

If the question is strictly "can I" - the answer is than "yes, you can, quite trivially":如果问题严格来说是“我可以” - 答案是“是的,你可以,非常简单”:

template<typename T>
int Three() const {
    return static_cast<const T*>(this)->Private();
}
    

However, I would not advise this, since one of the benefits of CRTP is that it is (almost) impossible to misuse the cast - static_cast will almost always be valid.但是,我不建议这样做,因为 CRTP 的好处之一是(几乎)不可能滥用static_cast - static_cast几乎总是有效的。

With a snippet shown above, one could easily make a mistake and provide wrong template argument, and make static_cast undefined behavior.使用上面显示的片段,人们很容易犯错误并提供错误的模板参数,并使static_cast行为未定义。

Conclusion - there is no benefit in using this approach, but one can find a drawaback.结论 - 使用这种方法没有任何好处,但可以找到一个缺点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM