如何为std::variant与boost::variant编写同实现模板特化
实现同时匹配std::variant与boost::variant的类模板特化
核心思路
类模板偏特化不支持直接在特化参数位置写逻辑或匹配两种不同类模板的实例,因此先实现统一的类型萃取判断目标类型是否为任意std::variant或boost::variant,再基于萃取结果约束偏特化的匹配范围,即可复用同一份特化逻辑,同时支持捕获variant内部的参数包。
兼容C++11及以上标准的实现
该版本基于类型萃取+SFINAE实现,无高版本C++特性依赖:
#include <variant> #include <iostream> #include <boost/variant.hpp> #include <type_traits> #include <tuple> // 类型萃取:判断是否为std::variant或boost::variant template <typename T> struct is_any_variant : std::false_type {}; // 匹配std::variant,捕获内部参数包 template <typename... Ts> struct is_any_variant<std::variant<Ts...>> : std::true_type { using inner_types = std::tuple<Ts...>; }; // 匹配boost::variant,捕获内部参数包 template <typename... Ts> struct is_any_variant<boost::variant<Ts...>> : std::true_type { using inner_types = std::tuple<Ts...>; }; // TypeChecker主模板,匹配非variant类型 template <typename T, typename = void> struct TypeChecker { void operator()() { std::cout << "I am other type\n"; } }; // 偏特化,仅当T是任意variant类型时匹配 template <typename T> struct TypeChecker<T, typename std::enable_if<is_any_variant<T>::value>::type> { // 如需使用variant内部参数包,可通过typename is_any_variant<T>::inner_types获取 void operator()() { std::cout << "I am either std::variant or boost::variant\n"; } }; int main() { TypeChecker<std::variant<int, float>>{}(); TypeChecker<boost::variant<int, float>>{}(); TypeChecker<int>{}(); return 0; }
C++20简化实现(基于Concept)
C++20标准下可以用Concept简化约束写法,代码可读性更高:
#include <variant> #include <iostream> #include <boost/variant.hpp> #include <concepts> #include <tuple> // 复用上述is_any_variant萃取定义Concept template<typename T> concept AnyVariant = is_any_variant<T>::value; // 主模板 template <typename T> struct TypeChecker { void operator()() { std::cout << "I am other type\n"; } }; // 特化匹配满足AnyVariant约束的类型 template <AnyVariant T> struct TypeChecker<T> { void operator()() { std::cout << "I am either std::variant or boost::variant\n"; } }; // main函数与上述版本完全一致
运行结果
两个版本编译运行后均输出符合预期的结果:
I am either std::variant or boost::variant I am either std::variant or boost::variant I am other type
注意事项
- 原示例代码中所有结构体定义末尾缺失分号,属于基础语法错误,会直接导致编译失败,编写时需要补齐。
- 不要为
std::variant<Ts...>和boost::variant<Ts...>分别编写两份独立的TypeChecker特化,后续修改逻辑时需要同步维护两份代码,容易出现逻辑不一致问题。
内容的提问来源于stack exchange,提问作者Arus23
相关产品推荐
相关产品推荐

