【问题标题】:Passing a custom deleter to std::unique_ptr with std::function object使用 std::function 对象将自定义删除器传递给 std::unique_ptr
【发布时间】:2014-08-27 08:44:19
【问题描述】:

我有以下工作代码来使用自定义删除器初始化 std::unique_ptr

class Dataset
{
    ...
private:
    class CustomGDALDatasetDeleter {
    public:
            void operator()(GDALDatasetH res) const {
                ::GDALClose(res);
            }
    };
    using ResourceType = std::unique_ptr<GDALDataset,
                                         CustomGDALDatasetDeleter>;
    ResourceType data;
};

后来我有这个代码:

data = ResourceType(static_cast<GDALDataset*>(::GDALOpen(filename.c_str(),
                                              static_cast<GDALAccess>(mode)))
);

当我对 std::function 对象和 lambdas 尝试相同的操作时,我得到 bad_function_call 异常:

class Dataset
{
    ...
private:
    std::function<void (GDALDatasetH)> del = [](GDALDatasetH res){::GDALClose(res);};
    using ResourceType = std::unique_ptr<GDALDataset,
                                         decltype(del)>;
    ResourceType data;

};

我在这里做错了什么?

【问题讨论】:

  • 您可能没有将删除器的副本传递给指针构造函数。
  • 一种可能更容易理解的看待它的方式是,编译器应该如何判断从知道删除器是std::function&lt;void (GDALDatasetH)&gt; 到知道它需要调用GDALClose?除了del 本身之外,没有任何内容包含该信息,unique_ptrdel 一无所知。
  • 是的,你是对的。据我了解,问题的原因是std::unqiue_ptr,当给定两个模板类型参数时,会尝试默认构造一个删除器类型的对象。但根据定义 lambda 没有,这会导致删除器为空。

标签: c++ c++11 lambda unique-ptr std-function


【解决方案1】:

您正在使用多态函数包装器,并且在默认构造时将其构造为空
因此,它会在调用时引发异常。

function() noexcept;

template <class A> function(allocator_arg_t, const A& a) noexcept;  

2 后置条件:!*this

20.9.11.2.4 函数调用[func.wrap.func.inv]

R operator()(ArgTypes... args) const

1 效果:INVOKE (f, std::forward&lt;ArgTypes&gt;(args)..., R) (20.9.2),其中 f*this 的目标对象 (20.9.1)。
2 返回:如果Rvoid 则为空,否则为INVOKE (f, std::forward&lt;ArgTypes&gt;(args)..., R) 的返回值。
3 次抛出:bad_function_call 如果!*this;否则,包装的可调用对象引发的任何异常。

在你第一次往data里面放东西的时候/之前设置deleter,就OK了。

【讨论】:

  • 谢谢,这行得通。但我不得不承认,我并不完全理解,为什么在构造指针时,在没有指定删除器对象的情况下使用仿函数进行相同的调用。
  • @Meiner:神奇的是默认构造对象的行为:大多数函子可以在默认构造状态下按预期工作,并且不需要抛出错误。您的甚至可能是无状态的,因此将针对最终性能进行优化。
  • 感谢您的提示。我在我的C++ Standard Library 书中找到了相应的条目。
猜你喜欢
  • 2013-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-09
  • 1970-01-01
相关资源
最近更新 更多