一些std::optional 构造函数使用这样的std::in_place_t标记参数:
template< class... Args >
explicit optional( std::in_place_t, Args&&... args );
Run Code Online (Sandbox Code Playgroud)
我看到这样的构造函数可以在没有就地标记的情况下实现,并使用一些enable-if魔法不参与不愿意的重载,即简单地说:
template< class... Args >
explicit optional( Args&&... args );
Run Code Online (Sandbox Code Playgroud)
为什么std::optional使用就地标记实现就地构造函数而不是一些启用魔法(并且没有标记)?
更新:问题略有更新,以强调我意识到简单地省略就地标记是行不通的.
我想问如何以std::optional有效的方式返回 an 并且我想使用std::make_optional(). 例如,让我们有这个代码片段:
std::optional<Path> CreateCanonicalPath(const std::string_view& path)
{
std::error_code errorCode;
const auto result = std::filesystem::weakly_canonical(std::filesystem::u8path(path), errorCode);
return !errorCode ? std::make_optional(result) : std::nullopt;
}
Run Code Online (Sandbox Code Playgroud)
result我特别感兴趣的是传递给是否有任何优化std::make_optional。使用起来会不会比较好std::make_optional(std::move(result))?
它是否可以防止任何 RVO 或 NVRO?这result是一个局部变量,但它并不完全在 return 语句中,所以我假设编译器不能单独使用 move 。
为什么下面的代码片段是合法的 C++ 代码?这是一个纯粹的理论问题 - 我没有想到任何用例:
#include <optional>
#include <vector>
#include <iostream>
int main() {
std::vector<int> v{1, 2, 3};
const std::optional<std::vector<int>> ov = v;
const auto nv = std::move(ov.value());
for (const auto& x : *ov) { std::cout << x; }
for (const auto& x : nv) { std::cout << x; }
}
Run Code Online (Sandbox Code Playgroud)
这产生了123123,但我不明白原因。
std::move应用于 a 的值const optional?optional ov仍然持有vector?是否ov.value()在内部创建一个临时副本,然后从中移动?
std::make_通过引入类模板参数推导(除了make_unique和make_shared),所有这些都被 C++17 变得多余。
那么重点是std::make_optional什么?至于我可以告诉它的确切同样的事情扣除导游的std::optional。
有没有std::make_optional比演绎指南更受欢迎的场景?
我正在将代码移植到 C++17,尝试尽可能使用新功能。我喜欢的一件事是使用std::optional在某些情况下可能会失败的函数中返回或不返回值的想法。
我很好奇这个新特性的可能用途,我正在考虑开始使用它来替换函数中的可选参数,所以:
void compute_something(int a, int b, const Object& c = Object(whatever)) {
// ...
}
Run Code Online (Sandbox Code Playgroud)
变成:
void compute_something(int a, int b, std::optional<Object> c) {
auto tmp = c.value_or(Object(whatever));
// ...
}
Run Code Online (Sandbox Code Playgroud)
根据官方文档:
如果一个可选项包含一个值,则保证该值作为可选对象占用空间的一部分进行分配,即永远不会发生动态内存分配。因此,即使定义了 operator*() 和 operator->() ,可选对象也建模对象,而不是指针。
因此,每次我们使用 std::optional 传递参数时,它意味着创建副本,如果对象很大,这可能会导致性能下降。
我喜欢这个想法,因为它使代码更简单易懂,但是有什么好处吗?
我正在审查C++ - 17 std::optional类模板的接口,并注意到reset和assignment来自nullopt未标记为constexpr.
这是疏忽还是有理由说这个操作不能标记为constexpr?
在阅读GCC的实现时,std::optional我发现了一些有趣的东西.我知道boost::optional实现如下:
template <typename T>
class optional {
// ...
private:
bool has_value_;
aligned_storage<T, /* ... */> storage_;
}
Run Code Online (Sandbox Code Playgroud)
但是libstdc ++和libc ++(以及Abseil)都实现了optional这样的类型:
template <typename T>
class optional {
// ...
private:
struct empty_byte {};
union {
empty_byte empty_;
T value_;
};
bool has_value_;
}
Run Code Online (Sandbox Code Playgroud)
他们看起来因为它们在功能上是相同的,但使用一个优于另一个有什么优势吗?(除了明显缺乏后者的新位置,这真的很好.)
我知道std::optional<T&>标准不支持这一点。这个问题是关于是否通过std::optional<T>&有性能优势
示例代码(https://godbolt.org/z/h56Pj6d6z)复制在这里
#include <ctime>
#include <iomanip>
#include <iostream>
#include <optional>
void DoStuff(std::optional<std::string> str) {
if (str) std::cout << "cop: " << *str << std::endl;
}
void DoStuffRef(const std::optional<std::string>& str) {
if (str) std::cout << "ref: " << *str << std::endl;
}
int main() {
std::optional<std::string> str = {};
DoStuff(str);
DoStuffRef(str);
str = "0123456789012345678901234567890123456789";
DoStuff(str);
DoStuffRef(str);
}
Run Code Online (Sandbox Code Playgroud)
(我的实际用例对于复杂的用户定义类型是可选的,但我希望长字符串在编译器方面也能做同样的事情)
在这种情况下,DoStuffRef与 相比,实际上是否节省了任何复制工作DoStuff?
我试图查看 godbolt 输出,但我不知道足够的汇编来确定。我确实看到,在 的情况下DoStuff,似乎std::optional<T>创建了一个不存在的临时文件DoStuffRef,所以我怀疑是的,optional …
我试图使用std :: optional但我的代码引发错误.
我指定#include <experimental/optional>和编译选项是-std=c++1z,-lc++experimental.
怎么用std::experimental::optional?
以下是代码:
#include <experimental/optional>
#include <iostream>
std::experimental::optional<int> my_div(int x, int y) {
if (y != 0) {
int b = x / y;
return {b};
}
else {
return {};
}
}
int main() {
auto res = my_div(6, 2);
if (res) {
int p = res.value();
std::cout << p << std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)
错误信息:
optional.cpp:17:21: error: call to unavailable member function 'value':
int p = res.value(); …Run Code Online (Sandbox Code Playgroud) 我正在使用 C++23std::optional添加,但我不知道如何优雅地访问对象的值(如果optional处于活动状态)。
我知道我可以使用if,但这就是C ++20 。
我真的很喜欢 C++23 API 的变化,但我不知道如何跳过实现身份的样板。例如:
#include <functional>
#include <iostream>
#include <optional>
void print(std::optional<std::string>& name) {
name.transform([](std::string& x) {
std::cout << x << std::endl;
// I just want to print, without modifying optional, but next line is required
return x;
});
}
int main() {
std::optional<std::string> name{{"Bjarne"}};
print(name);
}
Run Code Online (Sandbox Code Playgroud)
感觉就像std::optional缺少invoke会员功能一样。
注意:在我的示例中,我在转换后不会链接任何其他内容,但为了简洁起见,我关心可选内容是否被修改。
c++ ×10
stdoptional ×10
c++17 ×7
c++11 ×1
c++23 ×1
constexpr ×1
ctad ×1
optimization ×1
stdmove ×1
unions ×1