给定类 Foo
template <typename T>
class Foo
{
public:
...other methods..
void bar()
{
...
m_impl.doSomething();
...
}
void fun()
{
...
m_impl.doSomethingElse();
...
}
void fubar()
{
...
}
private:
T m_impl;
};
我想迎合 T 是 boost::shared_ptr 的情况。 在这种情况下,对类 Foo 的唯一更改是它应该调用
m_impl->doSomething();
代替
m_impl.doSomething();
我最终在同一 header 中定义了 FooPtr
template <typename T>
class FooPtr
{
public:
...other methods..
void bar()
{
...
m_pImpl->doSomething();
...
}
void fun()
{
...
m_pImpl->doSomethingElse();
...
}
void fubar()
{
...
}
private:
boost::shared_ptr<T> m_pImpl;
};
现在虽然该方法适用于我想与 Foo 一起使用的所有类, 问题是我有很多重复的代码和任何更改 我制作 Foo,我还必须制作 FooPtr。
如何重构代码?例如。有什么方法可以在编译时确定 T 是否属于 boost::shared_ptr 类型,然后仅专门化 bar 和 fun 方法来调用 -> 运算符?
编辑: 感谢您到目前为止的所有回答!我只需要一些时间来完成所有这些,看看哪种解决方案最适合我们的软件。
编辑 2: @Matthieu:这是我使用的测试代码
class FooImpl
{
public:
void doIt()
{
cout << "A" << std::endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Foo<FooImpl> foo;
foo.doSomething();
return 0;
}
最佳答案
Sylvain 写了一个 DRY 解决方案,但我不喜欢滥用继承。
使用包装类来统一接口(interface)很容易,尤其是因为指针语义工作得很好!
namespace details {
template <typename T>
struct FooDeducer {
typedef boost::optional<T> type;
};
template <typename T>
struct FooDeducer< T* > {
typedef T* type;
};
template <typename T>
struct FooDeducer< boost::shared_ptr<T> > {
typedef boost::shared_ptr<T> type;
};
} // namespace details
template <typename T>
class Foo {
public:
// methods
void doSomething() { impl->doIt(); }
private:
typedef typename details::FooDeducer<T>::type Type;
Type impl;
};
在这里,依靠提供 OptionalPointee 语义的 boost::optional
,我们几乎得到与指针相同的行为。
但我想强调的一点是复制行为的差异。 boost::optional
提供深拷贝。
关于c++ - 基于模板类型重构c++模板类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5324903/