标签: stdoptional

为什么std :: optional构造函数使用std :: in_place?

一些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使用就地标记实现就地构造函数而不是一些启用魔法(并且没有标记)?

更新:问题略有更新,以强调我意识到简单地省略就地标记是行不通的.

c++ c++17 stdoptional

13
推荐指数
1
解决办法
1110
查看次数

如何有效地返回 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++ optimization c++17 stdoptional

13
推荐指数
1
解决办法
4839
查看次数

为什么可以从 const std::Optional 中进行 std::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,但我不明白原因。

  1. 为什么 astd::move应用于 a 的值const optional
  2. 为什么optional ov仍然持有vector

是否ov.value()在内部创建一个临时副本,然后从中移动?

c++ stdmove stdoptional

13
推荐指数
1
解决办法
761
查看次数

`std::make_optional` 的重点是什么

std::make_通过引入类模板参数推导(除了make_uniquemake_shared),所有这些都被 C++17 变得多余。

那么重点是std::make_optional什么?至于我可以告诉它的确切同样的事情扣除导游的std::optional

有没有std::make_optional比演绎指南更受欢迎的场景?

c++ c++17 stdoptional ctad deduction-guide

12
推荐指数
1
解决办法
2087
查看次数

使用 std::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++ c++11 c++17 stdoptional

10
推荐指数
2
解决办法
5982
查看次数

constexpr std ::可选重置

我正在审查C++ - 17 std::optional类模板的接口,并注意到resetassignment来自nullopt未标记为constexpr.

这是疏忽还是有理由说这个操作不能标记为constexpr?

c++ constexpr c++17 stdoptional

10
推荐指数
1
解决办法
231
查看次数

std :: optional作为union vs char []/aligned_storage实现

在阅读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)

他们看起来因为它们在功能上是相同的,但使用一个优于另一个有什么优势吗?(除了明显缺乏后者的新位置,这真的很好.)

c++ placement-new unions c++17 stdoptional

9
推荐指数
2
解决办法
432
查看次数

通过引用传递 std::Optional&lt;T&gt; 是否真的可以节省复制?

我知道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 …

c++ stdoptional

9
推荐指数
2
解决办法
5335
查看次数

如何在C++中使用std :: 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++ c++17 stdoptional

8
推荐指数
1
解决办法
5280
查看次数

如何在不编写标识样板的情况下访问 C++23 std::Optional 中包含的值?

我正在使用 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++ stdoptional c++23

8
推荐指数
1
解决办法
1502
查看次数