如何访问仅限于同一类型的多个变体

问题描述 投票:0回答:2

我有一个关于使用排除非相等类型的通用访问者的问题。假设我有以下内容:

using StorageT = std::variant<std::vector<int>, std::vector<double>>;

StorageT process_data(const StorageT &lhs, const StorageT &rhs) {
    return std::visit([&](auto &&l, auto &&r){
        return kernel(l, r);   // some templated kernel 
    },
    lhs, rhs);
}

在外部,我验证变体

lhs
rhs
的底层存储类型是否匹配。我想编写一个通用访问者,而不为
lhs
rhs
的所有组合生成代码,其中底层变体类型不相同。

就目前情况而言,将生成两种基础变体类型的所有组合。 在 lambda 内部,我可以写

if constexpr(std::is_same_v<Tl, TR>) {
    return kernel( ... );
} else {
    // Do nothing
    // static_assert(false);
    // Throw exception
}

由于生成了

lhs
rhs
的所有组合,上述代码要么 a) 抱怨类型不匹配没有返回,b) 由于静态断言而失败,或者 c) 生成异常的代码路径它永远不会被抛出(由于类型的外部检查)。

对于

lhs
的基础类型不等于
rhs
的所有情况,避免生成代码的最佳方法是什么?

c++ variant
2个回答
0
投票

只需访问其中一种类型并使用它来确定另一种类型:

StorageT process_data(const StorageT &lhs, const StorageT &rhs) {
    return std::visit([&](auto &&l){
        auto &r = std::get<std::remove_cvref_t<decltype(l)>>(rhs);
        return kernel(l, r); 
    },
    lhs);
}

0
投票

这正是

std::unreachable
的目的。
来自文档:

调用未定义的行为。实现可以使用它来优化 不可能的代码会分支(通常在优化构建中)或 捕获它们以防止进一步执行(通常在调试版本中)。

(重点是我的)

由于编译器可以假设未定义的行为永远不会发生,因此这是优化掉您从未期望需要的代码片段的经典案例。

© www.soinside.com 2019 - 2024. All rights reserved.