如何转发声明自定义unique_ptr

时间:2015-11-04 13:49:01

标签: c++ unique-ptr forward-declaration

我在实现如下构造时遇到了问题。我的想法是我在一些头文件中定义了一个实用程序函数,它分配了某种资源。为了减轻客户自己释放它的必要性,我想把它包装成一个智能指针。 不幸的是,我不得不将删除器类型提供给客户端,并且无法正确地向前声明它。我当前的解决方案看起来像这样,导致多个定义错误,因为删除器是使用utilities.h的每个附加包含重新定义的。

这是我正在寻找的优雅解决方案?

// utilities.h
namespace foo
{
  auto del = []( MyResource* res) { Deallocate( res ); };
  std::unique_ptr<MyResource, decltype(del)> getResource( );
}

// utilities.cpp
namespace foo
{
  std::unique_ptr<MyResource, decltype(foo::del)> getResource( )
  {
    return std::unique_ptr<MyResource, decltype(foo::del)>( Allocate( ), del );
  }
}

2 个答案:

答案 0 :(得分:5)

使用普通类而不是lambda:

部首:

namespace foo {

  struct Deleter {
    void operator() (MyResource *res) const { Deallocate(res); }
  };

  std::unique_ptr<MyResource, Deleter> getResource();
}

来源:

namespace foo
{
  std::unique_ptr<MyResource, decltype(foo::del)> getResource( )
  {
    return std::unique_ptr<MyResource, Deleter>( Allocate( ) );
  }
}

这还有一个额外的好处,就是在创建指针时不必指定删除器 - 默认构造的Deleter就可以了。

答案 1 :(得分:0)

我建议Angew's answer超过这个主要是因为std::function中类型擦除的额外开销。很高兴知道这种方式也是可行的。

修复很简单:在头文件中有声明,源代码中有定义:

// utilities.h
namespace foo {
  using del_t = std::function<void(MyResource *)>;
  extern  del_t del;
  std::unique_ptr<MyResource, del_t> getResource();
}

// utilities.cpp
namespace foo {
  del = [](MyResource* res) {
      Deallocate(res);
  };
  std::unique_ptr<MyResource, del_t> getResource() {
      return std::unique_ptr<MyResource, del_t>(Allocate(), del);
  }
}