繁体   English   中英

从返回 std::optional 的 std::vector 的函数中获取结果到调用者

[英]Get result into the caller from a function returning std::optional of std::vector

我正在尝试使用std::vector之类的容器来操纵std::optional

我首先执行以下代码:

#include <iostream>
#include <vector>
#include <string>
#include <optional>

using namespace std;

using optional_vecs = std::optional<std::vector<std::string>>;

optional_vecs returnStrings()
{
    optional_vecs myVect(std::in_place); 
    myVect->emplace_back("Name");
    return myVect;
}

int main()
{
    for (auto e : returnStrings().value())
        std::cout << e << " ";

    return 0;
}

这里的问题是我在输出中什么也得不到:我猜是因为std::optional::value返回一个引用,因为在我的例子中它是对临时对象的引用。

所以为了解决这个问题,我尝试使用std::reference_wrapper如下:

using optional_vecs = std::optional<std::reference_wrapper<std::vector<std::string>>>;

optional_vecs returnStrings()
{
    optional_vecs myVect; 
    myVect->get().emplace_back("Name");
    return myVect;
}

现在我遇到了崩溃和错误:

  • 尝试添加字符串“名称”时发生崩溃。
  • 错误是当我尝试使用for-range循环时说the range for loop requires a suitable "begin" function and none was found.

下面的代码有效,但我不喜欢声明一个变量然后调用 Value():

int main()
{
    auto result = returnStrings();
    for (auto e : result.value())
        std::cout << e << " ";

    return 0;
}

那么我怎么能返回一个 std::optional 以functionName().Value()的方式持有一个std::vector

在前两种情况下,您的问题是,由于returnStrings()返回一个临时值,除非您实际捕获它返回的内容,否则 for 循环不会延长其生命周期。 捕获result.value()对你没有任何好处,因为它不会延长returnStrings()的生命周期。

那么我怎么能返回一个 std::optional 以functionName().Value()的方式持有一个 std::vector 。

您必须捕获functionName()的返回值。 你可以做你所做的,或者在 C++20 中,你可以使用 ranged for 的新init-statement版本,它是为这样的情况构建的,看起来像

for (auto&& opt_vec =  returnStrings(); auto e : opt_vec.value())
    std::cout << e << " ";

不幸的是,您必须使用后一种构造。

optional对象负责拥有vector C++ 不会递归地将生命周期延长到拥有被引用对象的对象,因此如果拥有对象被销毁(它会被销毁,因为它是临时的),被引用对象也将被销毁。

不过我要指出一件事:至少就 GCC 而言,这是有效代码

int main()
{
    for (auto ret = returnStrings(); auto e : ret.value())
        std::cout << e << " ";

    return 0;
}

更改为optional<reference_wrapper<vector>>也不起作用,因为原始returnStrings函数正在返回一个右值,这意味着如果不是用于复制省略,则原始对象将被移动分配,然后也被破坏。

因此,如果函数返回一个optional<vector>非常重要,那么您的 for 循环将需要一些东西来正确初始化可选对象本身。

在使用它的模板基础类型时,您需要使用std::optional包装器。 在您的情况下,它是std::string ,应该可以。

#include <iostream>
#include <vector>
#include <string>
#include <optional>

using namespace std;

using optional_vecs = std::optional<std::vector<std::string>>;

optional_vecs returnStrings()
{
    std::vector<std::string> myVect{};
    myVect.emplace_back("Name");
    return std::optional{ myVect };
}

int main()
{
    auto stringsOpt = returnStrings();

    if (stringsOpt) {
        for (auto& e : *stringsOpt)
            std::cout << e << " ";
    }

    return 0;
}

此代码实际上适用于 GCC。

PS:令人惊讶的是,您的源代码无法在 MSVC 上编译。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM