如何从已有std::variant创建仅含其子类型的新std::variant?
实现std::variant的子集类型转换
要实现将一个std::variant转换为仅包含其原类型子集的新std::variant,可以借助std::visit完成类型匹配与构造,同时通过编译期检查确保类型合法性。
核心实现代码
#include <variant> #include <type_traits> template<typename... TargetTypes, typename... SourceTypes> std::variant<TargetTypes...> cast_variant(const std::variant<SourceTypes...>& src) { // 编译期断言:目标variant的所有类型必须都在源variant的类型列表中 static_assert((std::disjunction_v<std::is_same<TargetTypes, SourceTypes>...> && ...), "目标类型必须全部是源variant类型的子集"); return std::visit( [](const auto& value) -> std::variant<TargetTypes...> { // 直接将值构造为目标variant,因已保证类型属于目标集合 return value; }, src ); }
代码说明
- 编译期检查:通过
static_assert结合std::disjunction,确保目标variant的每一种类型都存在于源variant的类型列表中,从根源避免无效转换请求。 - 类型匹配与构造:利用
std::visit遍历源variant的当前值,由于已保证该值属于目标类型集合,直接返回即可构造出目标类型的std::variant实例。
使用示例
#include <iostream> int main() { std::variant<int, const char*, bool> v1 = false; std::variant<int, bool> v2 = cast_variant<int, bool>(v1); // 验证转换结果 std::visit([](const auto& val) { std::cout << "v2的值是: " << val << std::endl; }, v2); return 0; }
运行这段代码会输出:v2的值是: 0(bool类型false在输出时会转为0)。
内容的提问来源于stack exchange,提问作者Jack Delahunt
相关产品推荐
相关产品推荐

