我可以使用模板成员函数作为 CRTP 的替代方案来实现静态多态性吗?
Can I use template member functions as an alternative to the CRTP in order to implement static polymorphism?
我想在 C++ 中使用静态多态性实现 template method 模式。
现在我有两个非常相似的classes A
和B
。它们具有相同的 public API 和完全相同的私有数据成员列表。大多数 public 成员函数的实现方式也相同,但对于其中一些成员函数,两个 classes 在实现方式上略有不同。
情况看起来有点像这样:
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;
};
我现在想通过将所有共享代码和数据成员移动到基 class 并从基 class 中委托给子 class 特定成员函数来减少代码重复]'。也就是说,像这样:
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;
};
我知道我可以使用 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;
}
现在开始我的问题。
如果不将 Base
设为模板 class, 是否有可能获得相同的结果?我可以使用例如完成同样的事情吗?模板成员函数?
/* 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;
};
如果问题是严格意义上的“我可以”- 答案是“是的,你可以,非常简单”:
template<typename T>
int Three() const {
return static_cast<const T*>(this)->Private();
}
但是,我不建议这样做,因为 CRTP 的好处之一是(几乎)不可能滥用转换 - static_cast
几乎总是有效。
使用上面显示的代码片段,很容易出错并提供错误的模板参数,并造成 static_cast
未定义的行为。
结论 - 使用这种方法没有任何好处,但可以找到缺点。
我想在 C++ 中使用静态多态性实现 template method 模式。
现在我有两个非常相似的classes A
和B
。它们具有相同的 public API 和完全相同的私有数据成员列表。大多数 public 成员函数的实现方式也相同,但对于其中一些成员函数,两个 classes 在实现方式上略有不同。
情况看起来有点像这样:
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;
};
我现在想通过将所有共享代码和数据成员移动到基 class 并从基 class 中委托给子 class 特定成员函数来减少代码重复]'。也就是说,像这样:
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;
};
我知道我可以使用 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;
}
现在开始我的问题。
如果不将 Base
设为模板 class, 是否有可能获得相同的结果?我可以使用例如完成同样的事情吗?模板成员函数?
/* 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;
};
如果问题是严格意义上的“我可以”- 答案是“是的,你可以,非常简单”:
template<typename T>
int Three() const {
return static_cast<const T*>(this)->Private();
}
但是,我不建议这样做,因为 CRTP 的好处之一是(几乎)不可能滥用转换 - static_cast
几乎总是有效。
使用上面显示的代码片段,很容易出错并提供错误的模板参数,并造成 static_cast
未定义的行为。
结论 - 使用这种方法没有任何好处,但可以找到缺点。