我有两个类A
和B
,如下所示,它们都实现了一个依赖于模板化方法g
的方法f
(在两者中重复相同的脚本)。如何避免重复g
类A
和B
的{{1}}方法中的代码?
class A {
public:
template<typename T>
void f() {}
void g() {
f<int>();
f<double>();
// etc.
}
};
class B {
public:
template<typename T>
void f() {}
void g() {
//The same scipt as that of A::g()
f<int>();
f<double>();
// etc.
}
};
如果f
未被模板化,那么我会将g
移动到基类,定义纯虚函数f
并简化A
和B
如下:
class Base {
public:
virtual Base() = default;
virtual void f() = 0;
void g() { f(); }
};
class A : public Base {
public:
void f() {}
};
class B : public Base {
public:
void f() {}
};
但是,我想知道f
被模板化时是否存在类似的方法。
答案 0 :(得分:2)
CRTP在这里工作正常。
它遵循一个最小的工作示例:
template<typename D>
class X {
public:
void g() {
D &d = static_cast<D&>(*this);
d.template f<int>();
d.template f<double>();
// etc.
}
};
class A: public X<A> {
public:
template<typename T>
void f() { }
};
class B: public X<B> {
public:
template<typename T>
void f() { }
};
int main() {
B b{};
b.g();
}
只要f
在派生类中公开,它就是一个很好的解决方案
否则,您必须在这些类中添加这些丑陋的friend class
语句:
class A: public X<A> {
private:
friend class X<A>;
template<typename T>
void f() { }
};
class B: public X<B> {
private:
friend class X<A>;
template<typename T>
void f() { }
};
答案 1 :(得分:1)
使g
成为非成员函数模板。
template<typename T>
void g(T& v) {
v.f<int>();
v.f<double>();
}
然后你可以传递A
或B
。如果您需要访问私人会员,您可以将其变成朋友。
答案 2 :(得分:0)
正如对@Benjamin Lindley回答的评论所述,我有以下解决方案,我决定在我的真实代码中使用。我相信它很简单,避免重复代码,g_helper
的实现可以隐藏在cpp文件中。
template<class T>
void g_helper(T& t) {
t.template f<int>();
t.template f<double>();
// etc.
}
class A {
public:
template<typename T>
void f() {}
void g() {
g_helper(*this);
}
};
class B {
public:
template<typename T>
void f() {}
void g() {
g_helper(*this);
}
};