2015-11-04 74 views
2

我有问题实现像下面这样的结构。这个想法是,我在某个头文件中定义了一个实用函数,它分配了某种资源。为了减轻客户自己解放它的必要性,我想将它包装成一个智能指针。 不幸的是,我不知何故需要删除类型的客户端,并有麻烦转发 - 适当地声明它。我现在的解决方案看起来像这样,导致多个定义错误,因为删除程序是重新定义的,每增加一个包含utility.h如何转发声明自定义unique_ptr

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

// 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); 
    } 
} 
+1

使删除器成为一个*函数*而不是一个lambda对象变量,并将该函数标记为'inline'? –

+0

@JoachimPileborg这应该是一个答案。 OTOH,它可以防止这种'unique_ptr'的默认构造。 – Angew

回答

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); 
    } 
} 
+0

这会在'std :: function'中引入类型擦除的额外开销。 – Angew

+0

@Angew是的。不知道任何其他方式来指定lambda的类型。如果这是一个问题,他应该去做一个简单的功能。 – bolov

5

使用,而不是一个拉姆达一个普通的类:

部首:

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就可以了。

+0

是的,你的方式更好 – bolov