Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/126.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ std::visit和std::variant用法 #包括 #包括 #包括 #包括 模板 结构承诺{ std::变体< std::单态, 标准::有条件的, std::异常\u ptr >结果!; T等待(u resume)const{ 断言(结果索引()>0); #如果1 //我想优化的旧代码 如果(结果索引()==2){ std::rethrow_异常(std::get(result)); } 如果constexpr(!std::is_void_v){ 返回std::get(结果); } #否则 //新代码,无法编译 return std::visit([](自动和参数化){ 使用TT=std::Decation\u t; 如果constexpr(!std::相同){ std::重试异常(arg); }否则,如果constexpr(!std::is\u void\u v){ 返回arg; } }); #恩迪夫 } }; 模板int Promise::wait_resume()常量; 模板std::exception_ptr Promise::Wait_resume()常量; 模板void Promise::wait_resume()常量;_C++_C++17_Std Variant - Fatal编程技术网

C++ std::visit和std::variant用法 #包括 #包括 #包括 #包括 模板 结构承诺{ std::变体< std::单态, 标准::有条件的, std::异常\u ptr >结果!; T等待(u resume)const{ 断言(结果索引()>0); #如果1 //我想优化的旧代码 如果(结果索引()==2){ std::rethrow_异常(std::get(result)); } 如果constexpr(!std::is_void_v){ 返回std::get(结果); } #否则 //新代码,无法编译 return std::visit([](自动和参数化){ 使用TT=std::Decation\u t; 如果constexpr(!std::相同){ std::重试异常(arg); }否则,如果constexpr(!std::is\u void\u v){ 返回arg; } }); #恩迪夫 } }; 模板int Promise::wait_resume()常量; 模板std::exception_ptr Promise::Wait_resume()常量; 模板void Promise::wait_resume()常量;

C++ std::visit和std::variant用法 #包括 #包括 #包括 #包括 模板 结构承诺{ std::变体< std::单态, 标准::有条件的, std::异常\u ptr >结果!; T等待(u resume)const{ 断言(结果索引()>0); #如果1 //我想优化的旧代码 如果(结果索引()==2){ std::rethrow_异常(std::get(result)); } 如果constexpr(!std::is_void_v){ 返回std::get(结果); } #否则 //新代码,无法编译 return std::visit([](自动和参数化){ 使用TT=std::Decation\u t; 如果constexpr(!std::相同){ std::重试异常(arg); }否则,如果constexpr(!std::is\u void\u v){ 返回arg; } }); #恩迪夫 } }; 模板int Promise::wait_resume()常量; 模板std::exception_ptr Promise::Wait_resume()常量; 模板void Promise::wait_resume()常量;,c++,c++17,std-variant,C++,C++17,Std Variant,是一个简单的函数,它执行以下操作: 如果变量的值为std::exception_ptr,请重新显示异常 如果变量的值为T(T由用户设置,也可能是std::exception_ptr),则将其返回。如果T的类型为void,则不执行任何操作 最初我使用.index()检查和std::get实现它。它可以工作,但是std::getthings会在内部生成额外的检查,并且std::\uu 1::\uu抛出\u坏的\u变量\u访问() 我想根据使用std::visit优化代码,但无法编译它 另一个问题是,

是一个简单的函数,它执行以下操作:

  • 如果变量的值为
    std::exception_ptr
    ,请重新显示异常
  • 如果变量的值为
    T
    (T由用户设置,也可能是std::exception_ptr),则将其返回。如果T的类型为void,则不执行任何操作
  • 最初我使用
    .index()
    检查和
    std::get
    实现它。它可以工作,但是
    std::get
    things会在内部生成额外的检查,并且
    std::\uu 1::\uu抛出\u坏的\u变量\u访问()

    我想根据使用std::visit优化代码,但无法编译它


    另一个问题是,当T的类型是std::exception\u ptr时,我如何知道是否应该抛出它?

    visit
    不会“优化”代码-它只是一个很好的模式,用于匹配
    变量,并且它特别有用,可以确保您不会忘记任何类型

    但是,
    visit
    的一个要求是每个备选方案必须返回相同的类型。这在您的用例中尤其有问题,因为只有一个备选方案应该返回。。。所以这不太合适。您还需要在
    访问
    中处理
    单一状态
    案例,而且您真的没有办法做到这一点(除了……扔?),所以您只是运气不好

    您以前的版本非常好,我只是用一些类型对其进行注释,以便更具表现力:

    struct Void { };
    
    template <typename T>
    struct Promise {
        using Value = std::conditional_t<std::is_void_v<T>, Void, T>;
    
        std::variant<
            std::monostate,
            Value,
            std::exception_ptr
        > result_;
    
        T await_resume() const {
            assert(not result_.valueless_by_exception());
            assert(not std::holds_alternative<std::monostate>(result_));
    
            if (auto* exc = std::get_if<std::exception_ptr>(&result)) {
                std::rethrow_exception(*exc);
            } else {
                if constexpr (not std::is_void_v<T>) {
                    return std::get<T>(result_);
                }
            }
        }
    }
    
    struct Void{};
    模板
    结构承诺{
    使用Value=std::conditional\u t;
    std::变体<
    std::单态,
    价值
    std::异常\u ptr
    >结果!;
    T等待(u resume)const{
    断言(不是结果\无值\被\异常()断言);
    assert(不是std::holds_alternative(result_));
    if(auto*exc=std::get_if(&result)){
    std::重新提交例外(*exc);
    }否则{
    如果constexpr(不是std::is\u void\u v){
    返回std::get(结果);
    }
    }
    }
    }
    
    我认为这比显式使用
    0
    1
    2
    要好一点


    另一个问题是,当
    T
    的类型是
    std::exception\u ptr
    时,我如何知道是否应该抛出它

    很简单:你不能扔它。在基于您的类型的泛型代码中,不要有完全不同的语义
    Promise::wait_resume()
    如果包含
    T
    ,则返回
    T
    <代码>承诺::等待恢复()
    返回一个
    异常\u ptr
    。那很好


    我想,实际上,在我上面的实现中,如果使用显式的
    get\u if
    ,就会变得模棱两可,这是不幸的。。。因此,也许
    0
    /
    1
    /
    2
    是最简单的方法。

    指的是@Barry的答案,这是我的最终版本:

    T wait_resume()常量{
    if(auto*pep=std::get_if(&result_)){
    标准::重新提交例外(*pep);
    }否则{
    如果constexpr(!std::is_void_v){
    auto*pv=std::get_if(&result_);
    断言(pv);
    返回*pv;
    }
    }
    }
    

    生成完美的asm,无额外检查,无错误的变量访问sh*t:

    如果与std::vector::operator[]不匹配,则
    std::variant
    是否具有与get\u或ub\u行为相同的方法?>但访问的一个要求是每个备选方法都必须返回相同的类型。我可以让他们返回相同的类型。只需在
    rethrow\u异常
    之后写入
    return T()
    。由于
    rethrow_exception
    声明为
    no_return
    ,因此
    rethrow_exception
    之后的代码不应生成任何代码。但它仍然无法编译。@CarterLi 1)No.2)
    返回t()只有在您的类型是默认可构造的情况下才有帮助,而且
    arg
    可以是
    T
    monostate
    ,所以这仍然是不同的类型。1)似乎
    *get_if(&variant)
    符合我的要求。由于取消对nullptr的引用是UB,编译器将删除返回nullptr的代码路径,包括if语句。