You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何结合std::is_invocable与std::variant、std::holds_alternative做调用检查

问题描述

我定义了如下std::variant类型:

using Value = std::variant<bool, float>;

std::holds_alternative可针对该变体包含的bool、float类型调用,但无法针对int等其他类型调用。现在想检查给定类型T时,std::holds_alternative<T>(const Value&)是否可调用,尝试了如下模板函数但编译失败:

template<class T>
void check() {
    if (std::is_invocable_v<decltype(std::holds_alternative<bool>), const Value&>) {
        std::cout << "callable";
    } else {
        std::cout << "not callable";
    }
}

请问正确的语法是什么?

解决方案

你的代码核心问题有两个:一是硬编码了bool类型,没有复用模板参数T;二是未使用if constexpr来隔离非法分支,导致非备选类型触发编译错误。以下是两种正确实现方式:

方式一:基于std::is_invocable_v的直接判断

利用if constexpr在编译期丢弃非法分支,同时将模板参数T代入std::holds_alternative进行判断:

#include <variant>
#include <iostream>
#include <type_traits>

using Value = std::variant<bool, float>;

template<class T>
void check() {
    if constexpr (std::is_invocable_v<decltype(std::holds_alternative<T>), const Value&>) {
        std::cout << "callable\n";
    } else {
        std::cout << "not callable\n";
    }
}

int main() {
    check<bool>();   // 输出callable
    check<float>();  // 输出callable
    check<int>();    // 输出not callable
}

关键说明

  • decltype(std::holds_alternative<T>)获取的是针对T实例化后的std::holds_alternative函数类型,结合const Value&参数,std::is_invocable_v能准确判断调用合法性。
  • if constexpr是必须的:当T不是Value的备选类型时,std::holds_alternative<T>的实例化会触发标准规定的格式错误,if constexpr会在编译期跳过不成立的分支,避免错误代码被实例化。

方式二:直接检查类型是否为变体备选类型

既然std::holds_alternative<T>可调用的前提是T是variant的备选类型之一,我们可以直接判断类型归属:

#include <variant>
#include <iostream>
#include <type_traits>

using Value = std::variant<bool, float>;

// 通用工具:判断类型T是否是Variant的备选类型
template<class T, class Variant>
struct is_variant_alternative : std::false_type {};

template<class T, class... Args>
struct is_variant_alternative<T, std::variant<Args...>> 
    : std::disjunction<std::is_same<T, Args>...> {};

template<class T, class Variant>
constexpr bool is_variant_alternative_v = is_variant_alternative<T, Variant>::value;

template<class T>
void check() {
    if constexpr (is_variant_alternative_v<T, Value>) {
        std::cout << "callable\n";
    } else {
        std::cout << "not callable\n";
    }
}

int main() {
    check<bool>();   // 输出callable
    check<float>();  // 输出callable
    check<int>();    // 输出not callable
}

这种方式更直观,直接从类型归属角度判断,避免了对std::holds_alternative的间接调用检查。

内容的提问来源于stack exchange,提问作者gimmeamilk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 19:38:36