我可以以某种方式返回带有常量引用的std :: optional来避免复制数据吗?

问题描述

假设我有一些基类,可以选择返回一些特定数据。它还提供了“ hasData”功能来检查此类特定数据是否可供使用

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; }
};

这很好,可以满足我的要求。但是'hasData'和'getData'是很好的候选者,可以用一个返回'std :: optional'的函数代替。 但是,当我尝试改善返回std :: optional的API时,我意识到我再也无法对内部数据返回“常量引用”了

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
};

一种可能性是使用std::optional<Arg1> m_data MyClassWithOptDerived-但对我来说并不好-派生类肯定具有数据,因此没有理由在其中存储std :: optional。此外,还需要将“ m_data”移到我绝对不希望的基类中

在这种示例中是否还有其他可能使用std :: optional并避免复制数据的可能性?

PS:我检查了诸如std::optional specialization for reference types之类的文章,似乎无法避免复制数据,我可能应该在此处使用“旧式”界面。

更新: 谢谢大家如此迅速的回复。对我有效的解决方案是使用std :: reference_wrapper。解决方案代码如下

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

解决方法

可选引用与指针相同。返回const Arg1 *

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...