c++ - 基于模板类型重构c++模板类

标签 c++ templates refactoring shared-ptr

给定类 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/

相关文章:

c++ - visual studio 不显示新成员

javascript - 我如何渲染 Bootstrap 切换

java - IntelliJ : How do I refactor without strings/comments/etc.?

c++ - FFmpeg API 示例 (encode_video.c) 无法正常工作

c++ - 用户终止进程时发出信号?

c++ - Qt:我应该使用哪个对象/项目来创建可点击的图标

javascript - 我怎样才能简化这个 jquery/javascript

c++ - 在另一个数组中使用一个数组的大小

c++ - 如何彻底改变 QAbstractTableModel 的底层数据?

java - 使 JavaDoc 对重构具有鲁棒性