如何更简洁地指定从std::variant获取的类型,避免重复代码?
解决方案
通过一个零开销的泛型封装即可实现符合要求的写法,既满足DRY原则,又完全保留原有异常逻辑,不会触发隐式类型转换。
实现代码
先定义通用的精确取值模板函数,所有逻辑在编译期展开,无额外运行时成本:
#include <variant> template <typename T, typename... Ts> T get_exact(const std::variant<Ts...>& v) { return std::get<T>(v); }
初始化代码可简化为如下形式,无需重复书写类型、无需使用decltype:
std::variant<float, int> v[2] = foo(); int a = get_exact(v[0]); float b = get_exact(v[1]);
行为特性
- 异常逻辑与原代码完全一致:variant存储类型和目标变量类型不精确匹配时,会正常抛出
std::bad_variant_access,原有异常处理逻辑无需修改。 - 无隐式类型转换:如果variant存储float,尝试赋值给int变量时会直接抛出异常,不会触发
static_cast类的数值转换,完全符合要求。 - 自动类型推导:编译器会根据赋值目标的类型自动确定
std::get的模板参数,无需重复书写类型名,解决DRY违规问题。 - 额外编译期检查:如果目标变量类型不在variant的备选类型列表中,编译阶段就会报错,安全性比原写法更高。
- 零性能损耗:模板实例化后的代码与手写
std::get<int>(v[0])、std::get<float>(v[1])完全等价,无任何额外开销。
补充
C++20及以上环境可以选择在局部用lambda实现相同逻辑,但独立泛型函数的复用性更高。标准库没有提供对应原生能力,因为std::get的模板参数仅通过入参推导,不会根据返回值的赋值目标倒推类型。
内容的提问来源于stack exchange,提问作者MSalters
相关产品推荐
相关产品推荐

