I'm pretty new in move and lvalue semantics. And I have the impression I'm doing it wrong. Here
the code I want to be able to write once FunctContainer
is implemented:
std::function<double(double)> f = [](double x){return (x * x - 1); };
FunctContainer fc1 = FunctContainer(f);
FunctContainer fc2 = FunctContainer([](double x){return (x * x - 1); });
I want to write FunctContainer
's ctors so that the lifetime of the function stored in fc1
is the one of f
and the lifetime in fc2
of the contained function is the lifetime of fc2
itself.
I have written something (see below) but I'm not really satisfied (I got it wrong).
This is correct c++ but wrong behavior: f_
expires after the call to the constructor when f_
is an rvalue.
class FunctContainerWRONG{
public:
IntegrandNotProjecting(const std::function<double(double)>& function)
: f_(function){}
IntegrandNotProjecting(const std::function<double(double)>&& function)
: f_(std::move(function)){}
const std::function<double(double)>& f_;
private:
};
This looks awful at me and probably is not correct c++ but is intended to explain in pseudocode what the desired behavior looks like. If possible I want to avoid to constuct a brand new object and I just want to let my object "persist":
class FunctContainer{
public:
FunctContainer(const std::function<double(double)>& function)
: f_p(nullptr),
f_(function){}
FunctContainer(const std::function<double(double)>&& function)
: f_p()std::make_shared<std::function<double(double)>>(function)),
f_(*f_p){}
private:
std::shared_ptr<std::function<double(double)>> f_p;
const std::function<double(double)>& f_;
};
Since C++17 there is class template argument deduction with user-defined deduction guides (Class Template Argument Deduction). With that you can solve your problem as follows:
Forwarding references and reference collapsing rules can help you achieve this easily.
When you invoke
makeFunctContainer
with an lvalue,T
will be an lvalue reference. This means that you'll store an lvalue reference insideFucntContainer
.When you invoke
makeFunctContainer
with an rvalue,T
will be a value. This means that you'll store a value insideFucntContainer
.Example usage: