需要帮助使用模板解决运行时多态性

时间:2012-03-28 14:09:49

标签: c++ templates polymorphism raii

我有一段时间用于封装C库FILE *的模板。这是一个相当经典的实现,指向FILE *的包装类的共享指针。使用我自己的自定义共享指针的原因是为一些C库FILE *免费函数提供免费的函数替换,以便允许我直接替换与FILE *一起使用的遗留代码。

我所使用的实现使用内部包装器,保证在删除时,拥有的FILE *将被关闭。 RAII。

但是,我需要创建一个类似的系统来处理我想要刷新底层FILE *的情况。截断,而不是在最后一个FILE *持有者被销毁时关闭。也就是说,我有一个原始保证关闭类型的开放FILE *,但是希望将另一个FILE *的副本分发给另一个对象,该对象将保证当它的最后一个实例被销毁时,它会冲洗和截断FILE *而不是关闭它,因此让我的基础FILE *处于打开状态,但流的内容刷新到磁盘(文件大小只反映有效内容)。

我已经为编译时多态性解决了这个问题。但我需要一些方法来提供运行时多态性,我真的不想在这个场景中放置另一层 - 间接(即如果我使用多态指针来自动关闭或自动刷新FILE *包装器,我是金色的 - 但我真的希望保持我现在拥有的相同深度并隐藏自定义共享指针实现中的多态性。

基本上,如果我有:

template <class WrapperT>  
class FilePointerT  
{  
public:
  // omitted: create, destroy, manipulate the underlying wrappered FILE*  
private:
  WrapperT * m_pFileWrapper;  
  ReferenceCount m_rc;  
}

显然,省略了大量细节。可以这么说,当删除最后一个这些对象时,它会删除最后一个m_pFileWrapper(事实上,如果我重写这段代码,我可能会使用boost :: shared_ptr)。

无论如何,这里真正的问题是我对如何使用FilePointerT&lt; WrapperT&gt;感到困惑。其WrapperT可以变化,但可以在代码中使用,就好像它们都是一样的(毕竟它们是,因为WrapperT的实现对FilePointerT的结构和接口(基本上是一个pimpl)没有任何影响。 / p>

我可以声明什么可能包含任何FilePointerT&lt; WrapperT&gt;对于任何WrapperT?

或者,我如何更改FilePointerT的定义以便允许我提供特定的WrapperT?

3 个答案:

答案 0 :(得分:3)

你不能简单地使用std::shared_ptr<FILE *, deleter_function>吗?为免费功能提供普通的重载,没有有趣的模板malarky。

答案 1 :(得分:2)

您可以使用type erasure透明地处理所有版本的FilePointerT。正如上面的海报所提到的,我也会采用shared_ptr方法,实际上删除器甚至不是shared_ptr签名的一部分,因此你可以在保持类型不变的同时改变删除器。

答案 2 :(得分:0)

对于它的价值,我最终做的是将包装器嵌入到FilePointer类中,而不是将其作为其类型的一部分。

class FilePointer
{
public:
    // create using a file wrapper (which will handle policy issues)
    FilePointer(FileWrapper * pfw) : m_pFileWrapper(pfw) { }

protected:
    FileWrapper *   m_pFileWrapper; // wrapper has close/flush policy
    ReferenceCount  m_references;   // reference count
};

然后文件指针将实际工作委托给包装器,包装器实现所需的策略,并且可以编写代码来使用FilePointer。

显然还有其他方法可以做到这一点,但这就是我的目标。