如何实现适配std::variant及其派生类的alternative判断concept
支持std::variant派生类的备选类型判断Concept实现
要让concept支持继承自std::variant的派生类型,核心思路是先提取出派生类对应的基类std::variant<Ts...>,再判断目标类型是否属于Ts...中的一员。以下是完整实现:
完整代码实现
#include <variant> #include <tuple> #include <type_traits> // 辅助推导函数:从std::variant实例中提取备选类型的元组 template<typename... Ts> constexpr auto get_variant_alternatives_tuple(std::variant<Ts...> const&) -> std::tuple<Ts...>; // 辅助Trait:获取类型对应的std::variant备选类型元组 template<typename T> struct variant_alternatives { using type = decltype(get_variant_alternatives_tuple(std::declval<T const&>())); }; // 对非std::variant/非派生类型触发断言 template<typename T> requires (!requires { get_variant_alternatives_tuple(std::declval<T const&>()); }) struct variant_alternatives<T> { static_assert(false, "mystery_c: 类型必须是std::variant或其派生类"); }; template<typename T> using variant_alternatives_t = typename variant_alternatives<T>::type; // 最终的判断Concept template<typename AlternativeType, typename VariantType> concept mystery_c = []<typename... Ts>(std::tuple<Ts...>) { return (std::is_same_v<AlternativeType, Ts> || ...); }(variant_alternatives_t<VariantType>{}); // 测试用例 struct derived_var : std::variant<int, float> {}; int main() { // 测试派生类 static_assert(mystery_c<int, derived_var>); static_assert(!mystery_c<std::string, derived_var>); // 测试原生std::variant using simple_variant = std::variant<int, float>; static_assert(mystery_c<int, simple_variant>); static_assert(!mystery_c<std::string, simple_variant>); return 0; }
实现说明
- 辅助推导函数:
get_variant_alternatives_tuple利用函数模板参数推导,从std::variant<Ts...>的实例中返回包含所有备选类型的std::tuple<Ts...>。由于派生类可以隐式转换为基类std::variant,该函数同样能处理派生类型。 - 辅助Trait:
variant_alternatives通过decltype获取推导函数的返回类型,从而拿到备选类型元组;针对非variant类型的特化会触发编译断言,给出明确错误提示。 - 核心Concept:
mystery_c利用C++20的模板lambda,展开备选类型元组的模板参数,通过折叠表达式判断目标类型是否是其中一员。
这个实现同时支持原生std::variant和其派生类,完全满足需求。
内容的提问来源于stack exchange,提问作者Basti
相关产品推荐
相关产品推荐

