I have the following working code to initialize a std::unique_ptr
with a custom deleter:
class Dataset
{
...
private:
class CustomGDALDatasetDeleter {
public:
void operator()(GDALDatasetH res) const {
::GDALClose(res);
}
};
using ResourceType = std::unique_ptr<GDALDataset,
CustomGDALDatasetDeleter>;
ResourceType data;
};
Later I have this code:
data = ResourceType(static_cast<GDALDataset*>(::GDALOpen(filename.c_str(),
static_cast<GDALAccess>(mode)))
);
When I try the same with a std::function
object and lambdas
I get a bad_function_call
exception:
class Dataset
{
...
private:
std::function<void (GDALDatasetH)> del = [](GDALDatasetH res){::GDALClose(res);};
using ResourceType = std::unique_ptr<GDALDataset,
decltype(del)>;
ResourceType data;
};
What am I doing wrong here?
You are using a polymorphic function wrapper, and when default-constructing it is constructed empty.
Thus, it throws an exception on invocation.
function() noexcept;
template <class A> function(allocator_arg_t, const A& a) noexcept;
2 Postconditions:
!*this
.
20.9.11.2.4 function invocation [func.wrap.func.inv]
R operator()(ArgTypes... args) const
1 Effects:
INVOKE (f, std::forward<ArgTypes>(args)..., R)
(20.9.2), wheref
is the target object (20.9.1) of*this
.
2 Returns: Nothing ifR
isvoid
, otherwise the return value ofINVOKE (f, std::forward<ArgTypes>(args)..., R)
.
3 Throws:bad_function_call
if!*this
; otherwise, any exception thrown by the wrapped callable object.
Set the deleter before / at the time you first put something into data
, and all is ok.