Let me start with a C++ code that simplifies my issues I faced in the actual code base. I compiled it with --std=c++20 and --std=c++17. The first for-loop below was okay; the second for-loop, which returns std::optional<Container> was not, for all of the multiple containers I have tried. I'd like to understand why:
#include <iostream>
#include <optional>
#include <string>
#include <unordered_set>
std::unordered_set<std::string> GenerateSet() {
std::unordered_set<std::string> names = {"a", "b"};
return names;
}
std::optional<std::unordered_set<std::string>> GenerateOptionalSet() {
std::unordered_set<std::string> names = {"a", "b"};
return names;
}
int main() {
std::cout << "When a set is returned: {";
for (const auto& e : GenerateSet()) {
std::cout << e << " ";
}
std::cout << "}" << std::endl;
std::cout << "When a optional of a set is returned: {";
for (const auto& e : GenerateOptionalSet().value()) {
std::cout << e << " ";
}
std::cout << "}" << std::endl;
return 0;
}
The result was segmentation faults at runtime (fairly recent clang) or no iteration at all in the second for-loop (fairly old gcc on an archaic Linux box).
Here's the URL I referred to regarding the std::optional<T>::value():
std::optional::value() from cppreference.com
There seem to be 4 different versions. I was not quite sure which version of the 4 overridden functions would be invoked and why it does not work as I expected (i.e. just looping over the value of the returned, temporary std::optional<T>).
value()gives you a reference to the object contained within the optional, so the thing that needs lifetime extension isn't available to be extended