标签: stdoptional

是否可以将对象设置为null?

在我的代码中,我检查以查看对象是否为空/空.

有没有办法将对象设置为null?

c++ null object is-empty stdoptional

36
推荐指数
3
解决办法
10万
查看次数

我可以将不可移动且不可复制的函数结果复制删除为可选值吗?

我想存储一个不平凡的类型,它是不可移动且不可复制的std::optional。然而该对象是由自由函数构造的。(例子

struct Foo {
    Foo();
    Foo(Foo const&) = delete;
    Foo(Foo&&) = delete;
    Foo& operator=(Foo const&) = delete; // added for completeness
    Foo& operator=(Foo&&) = delete; // added for completeness
    ~Foo();
};
Foo foo();
Run Code Online (Sandbox Code Playgroud)

无需改变Foofoo()

感谢复制省略,我已经可以做到这一点:

Foo f1 = foo();
Run Code Online (Sandbox Code Playgroud)

这也可以编译,因为std::optional只要求存储的类型是可破坏的:

std::optional<Foo> f2;
f2.emplace();
Run Code Online (Sandbox Code Playgroud)

但我无法填写f2函数结果:

f2 = foo(); // no
f2.emplace(foo()); // no
Run Code Online (Sandbox Code Playgroud)

显然,因为这需要复制或移动Foo. 这可能是不可能的,但我是否忽略了一些事情?

c++ copy-elision stdoptional

28
推荐指数
3
解决办法
1555
查看次数

为什么 std::optional::value_or() 采用 U&amp;&amp; 而不是 T&amp;&amp; ?

cppreference上,我们可以看到std::optional采用默认值U&&而不是T&&

它使我无法编写以下代码:

std::optional<std::pair<int, int>> opt;
opt.value_or({1, 2}); // does not compile
opt.value_or(std::make_pair(1, 2)); // compiles
Run Code Online (Sandbox Code Playgroud)

但是,我发现使用 没有任何好处U&&,因为U必须可以转换为T此处。

所以,考虑下面的代码,如果我们有一些U不同于 的类型T,那么就不会有完美的匹配。然而,通过执行隐式转换,我们仍然可以解析我们的调用:

template< class U >
constexpr T value_or( T&& default_value ) const&;
Run Code Online (Sandbox Code Playgroud)

我有以下代码来测试模板函数是否可以接受需要额外隐式转换才能完美匹配的参数,并且它可以编译:

#include <cstdio>
#include <optional>
#include <map>

struct A {
    int i = 1;
};

struct B {
    operator A() const {
        return A{2};
    }
};

template <typename T>
struct C { …
Run Code Online (Sandbox Code Playgroud)

c++ c++17 stdoptional

21
推荐指数
3
解决办法
3005
查看次数

如何展平嵌套的 std::optional?

注意:这个问题被简要标记为this的重复,但它不是一个完全重复的,因为我专门询问 std::optionals 。如果您关心一般情况,仍然是一个值得阅读的好问题。

假设我有嵌套的选项,像这样(愚蠢的玩具示例):

struct Person{
    const std::string first_name;
    const std::optional<std::string> middle_name;
    const std::string last_name;
};
struct Form{
    std::optional<Person> person;
};
Run Code Online (Sandbox Code Playgroud)

和这个垃圾邮件功能:

void PrintMiddleName(const std::optional<Form> form){
    if (form.has_value() && form->person.has_value() && form->person->middle_name.has_value()) {
        std::cout << *(*(*form).person).middle_name << std::endl; 
    } else {
        std::cout << "<none>"  << std::endl; 
    }
}
Run Code Online (Sandbox Code Playgroud)

展平此可选检查的最佳方法是什么?我做了这样的东西,它不是可变参数,但我不太关心(membr3如果真的有必要,我可以再添加一个级别(用 重载),除此之外的一切都是糟糕的代码)。

template<typename T, typename M>
auto flatten_opt(const std::optional<T> opt, M membr){
    if (opt.has_value() && (opt.value().*membr).has_value()){
        return std::optional{*((*opt).*membr)};
    }
    return decltype(std::optional{*((*opt).*membr)}){};
}

template<typename T, typename M1, typename M2> …
Run Code Online (Sandbox Code Playgroud)

c++ c++20 stdoptional

19
推荐指数
3
解决办法
888
查看次数

clang 5:std :: optional instantiation screw std :: is_constructible trait of the parameter type

当切换到c ++ 17并用std::optional标准解决方案替换自定义解决方案时,检测到clang 5的一个非常奇怪和意外的行为.出于某种原因,emplace()由于对std::is_constructible参数类的特征的错误评估而被禁用.

在复制之前必须满足一些特定的前提条件:

#include <optional>

/// Precondition #1: T must be a nested struct
struct Foo
{
    struct Victim
    {
        /// Precondition #2: T must have an aggregate-initializer
        /// for one of its members
        std::size_t value{0};
    };

    /// Precondition #3: std::optional<T> must be instantiated in this scope
    std::optional<Victim> victim;

    bool foo()
    {
        std::optional<Victim> foo;

        // An error
        foo.emplace(); 
        /// Assertion is failed
        static_assert(std::is_constructible<Victim>::value);
    }
};
Run Code Online (Sandbox Code Playgroud)

godbolt.org上的实例


更改任何前提条件并按预期编译.标准中是否存在一些未知的不一致性,使得clang在符合要求时拒绝此代码?

作为旁注:GCC 7.1 …

c++ language-lawyer c++17 stdoptional

16
推荐指数
1
解决办法
691
查看次数

std :: optional :: value_or() - 懒惰参数评估

是否有可能以std::optional::value_or(expr)懒惰的方式评估参数,所以expr仅在没有值的情况下计算?

如果没有,什么是适当的替代品?

c++ stl c++17 stdoptional

15
推荐指数
2
解决办法
1374
查看次数

std :: optional如何永远不会“异常无价值”?

std::variant可以进入一种称为“ 异常无价值 ”的状态。

据我了解,这是导致移动分配抛出异常的常见原因。不能保证该变体的旧值不再存在,预期的新值也不是。

std::optional,但是没有这种状态。cppreference提出了大胆的主张:

如果引发异常,则* this ...的初始化状态不变,即,如果对象包含一个值,则它仍然包含一个值,反之亦然。

如何std::optional避免变得“异常无价值”而std::variant不能避免?

c++ c++17 stdoptional std-variant

14
推荐指数
3
解决办法
367
查看次数

C++23 可选的一元绑定和一元返回是什么?

C++23std::optional终于得到了一些非常有用的补充。

由于我对 FP 的了解非常原始,我想知道以下两个操作的语法是什么(根据我的谷歌搜索,这是两个基本的一元操作):

  1. 单子绑定
  2. 单子回归

我最好的猜测是:

单子绑定就是变换

Monadic 返回只是 C++17std::optional 构造函数(8)

c++ monads stdoptional c++23

14
推荐指数
2
解决办法
2536
查看次数

从 std::Optional 中获取值

实际上如何从可选项中获取值?意思是取得 中的值的所有权std::optional并将其替换为std::nullopt(或将其交换为另一个值)?

例如,在 Rust 中,您可以.unwrap执行Option或执行类似的操作foo.take().unwrap()。我正在尝试用 C++ 做类似的事情optional

c++ option-type c++17 stdoptional

14
推荐指数
1
解决办法
1万
查看次数

C++23的可选::transform和可选::and_then有什么区别?

C++23 添加了一些关于可选值的“monadic-style”功能,作为以下方法optional<T>

optional<T>::and_then()(并忽略 的限定符this):

template<class F> constexpr auto and_then(F&& f); 
Run Code Online (Sandbox Code Playgroud)

返回对包含的值(如果存在)调用 f 的结果。否则,返回返回类型的空值。

optional<T>::transform()(并忽略 的限定符this):

template<class F> constexpr auto transform(F&& f);
Run Code Online (Sandbox Code Playgroud)

如果包含一个值,则返回一个包含对所包含值std::optional调用的结果的。否则,返回此类类型的空值。f*thisstd::optional

那么,这两个函数不是在做同样的事情吗?

c++ monads monad-transformers stdoptional c++23

14
推荐指数
1
解决办法
2008
查看次数