我有一个关于使用排除非相等类型的通用访问者的问题。假设我有以下内容:
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
的所有情况,避免生成代码的最佳方法是什么?
只需访问其中一种类型并使用它来确定另一种类型:
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);
}
std::unreachable
的目的。调用未定义的行为。实现可以使用它来优化 不可能的代码会分支(通常在优化构建中)或 捕获它们以防止进一步执行(通常在调试版本中)。
(重点是我的)
由于编译器可以假设未定义的行为永远不会发生,因此这是优化掉您从未期望需要的代码片段的经典案例。