Suppose I have some base class which can optionally return me some specific data. It also provides me 'hasData' function to check if such specific data is available for usage
class MyClassBase {
public:
virtual bool hasData() const { return false; }
virtual const Arg1& getData() const { throw std::runtime_error("No data"); }
};
class MyClassDerived: public MyClassBase {
Arg1 m_data = Arg1(10);
public:
bool hasData() const override { return true; }
// Good - no copy constructor for data as I want
const Arg1& getData() const override { return m_data; }
};
This works well and does what I want. But 'hasData' and 'getData' are good candidates to be replaced by one function returning 'std::optional'. But when I tried to improve API returning std::optional, I realized that I can't return a 'const reference' anymore to my internal data
class MyClassWithOptBase {
public:
virtual std::optional<Arg1> getData() const { return std::nullopt; }
};
class MyClassWithOptDerived: public MyClassWithOptBase {
Arg1 m_data = Arg1(10);
public:
// Bad - copy constructor is created for my data!
std::optional<Arg1> getData() const override { return m_data; }
// std::optional<const Arg1 &> - doesn't compile as references are not allowed
// const std::optional<Arg1> & - can't return reference to temporary object
};
One possibility is to use std::optional<Arg1> m_data
MyClassWithOptDerived - but it doesn't look nice for me - derived class definitely has data and there shall be no reason to store std::optional in it. Also there will be need to move 'm_data' to base class which I definitely don't want
Any other possibility to use std::optional in such example and avoid copying of data?
PS: I checked some articles like std::optional specialization for reference types and seems that it is not possible to avoid copy of data and I probably should live with 'old-style' interface here.
Update: Thank you everyone for such quick responses. Solution that works for me is to use std::reference_wrapper. The solution code will look like
class MyClassWithOptBase {
public:
virtual std::optional<std::reference_wrapper<const Arg1>> getData() const {
return std::nullopt;
}
};
class MyClassWithOptDerived : public MyClassWithOptBase {
Arg1 m_data = Arg1(10);
public:
// Good as well - no copy constructor for my data!
std::optional<std::reference_wrapper<const Arg1>> getData() const override {
return m_data;
}
};
// In 'main'
MyClassWithOptDerived opt;
auto res = opt.getData();
//Then res->get() will return me 'const Arg1&' as I want and no copy constructor will be invoked