从返回 std::optional of 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
return 一个引用,在我的例子中它是一个临时的引用。
所以为了解决这个问题,我尝试使用 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;
}
现在我遇到了崩溃和错误:
- 尝试添加字符串 "name" 时发生崩溃。
- 错误是当我尝试使用
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;
}
那我怎么能return一个std::optional拿着一个std::vector
挡着functionName().Value()
.
您需要在使用 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。
P.S。 : 令人惊讶的是,您的源代码无法在 MSVC 上编译。
您在前两种情况下的问题是,由于 returnStrings()
return 是临时的,for 循环不会延长其寿命,除非您实际捕获它 return 的内容。捕获 result.value()
对你没有任何好处,因为它不会延长 returnStrings()
.
的生命周期
So how could I return an std::optional holding a std::vector in the way functionName().Value()
.
您必须捕获 functionName()
的 return。你可以做你所做的,或者在 C++20 中,你可以使用新的 init-statement 版本的范围,它是为这样的情况构建的,看起来像
for (auto&& opt_vec = returnStrings(); auto e : opt_vec.value())
std::cout << e << " ";
不幸的是,您必须使用后一种构造。
optional
对象负责拥有 vector
。 C++ 不会递归地延长拥有被引用对象的对象的生命周期,因此如果拥有对象被销毁(它会被销毁,因为它是临时的),被引用对象也将被销毁。
有一件事我要指出:至少就 GCC 而言,this is valid code:
int main()
{
for (auto ret = returnStrings(); auto e : ret.value())
std::cout << e << " ";
return 0;
}
更改为 optional<reference_wrapper<vector>>
也不起作用,因为原始 returnStrings
函数是 returning 右值,这意味着如果不是复制省略,原始对象将被移动分配,然后也被破坏。
因此,如果函数 return 和 optional<vector>
非常重要,那么您的 for 循环将需要一些东西来正确初始化可选对象本身。
我正在尝试使用像 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
return 一个引用,在我的例子中它是一个临时的引用。
所以为了解决这个问题,我尝试使用 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;
}
现在我遇到了崩溃和错误:
- 尝试添加字符串 "name" 时发生崩溃。
- 错误是当我尝试使用
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;
}
那我怎么能return一个std::optional拿着一个std::vector
挡着functionName().Value()
.
您需要在使用 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。
P.S。 : 令人惊讶的是,您的源代码无法在 MSVC 上编译。
您在前两种情况下的问题是,由于 returnStrings()
return 是临时的,for 循环不会延长其寿命,除非您实际捕获它 return 的内容。捕获 result.value()
对你没有任何好处,因为它不会延长 returnStrings()
.
So how could I return an std::optional holding a std::vector in the way
functionName().Value()
.
您必须捕获 functionName()
的 return。你可以做你所做的,或者在 C++20 中,你可以使用新的 init-statement 版本的范围,它是为这样的情况构建的,看起来像
for (auto&& opt_vec = returnStrings(); auto e : opt_vec.value())
std::cout << e << " ";
不幸的是,您必须使用后一种构造。
optional
对象负责拥有 vector
。 C++ 不会递归地延长拥有被引用对象的对象的生命周期,因此如果拥有对象被销毁(它会被销毁,因为它是临时的),被引用对象也将被销毁。
有一件事我要指出:至少就 GCC 而言,this is valid code:
int main()
{
for (auto ret = returnStrings(); auto e : ret.value())
std::cout << e << " ";
return 0;
}
更改为 optional<reference_wrapper<vector>>
也不起作用,因为原始 returnStrings
函数是 returning 右值,这意味着如果不是复制省略,原始对象将被移动分配,然后也被破坏。
因此,如果函数 return 和 optional<vector>
非常重要,那么您的 for 循环将需要一些东西来正确初始化可选对象本身。