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

使用std::is_invocable无法检测模板成员函数serialise_deserialise的问题

问题

尝试用std::is_invocable检测模板参数类型是否存在名为serialise_deserialise()的成员函数,初始代码报错:'MySerializableType::serialise_deserialise': incorrect argument to 'decltype'。修改检测语句为std::is_invocable_v<decltype(&U::template serialise_deserialise<serialiser_deserialiser>), serialiser_deserialiser>后,static_assert仍失败,即使改用int作为参数也无法解决,为何无法识别U存在serialise_deserialise函数?

代码示例:

template <bool bIsInSerialiseMode>
struct serialiser_deserialiser
{
    template <typename U>
    void read_or_write(U& obj_to_write)
    {
        constexpr bool bDoesTypeHaveSerialiseDeserialiseFunction = std::is_invocable_v<decltype(&U::serialise_deserialise), serialiser_deserialiser>;

        //static_assert (bDoesTypeHaveSerialiseDeserialiseFunction);
    
        if constexpr (bDoesTypeHaveSerialiseDeserialiseFunction) 
        /* SOMETHING*/;
        else ; 
    }
};

struct MySerializableType
{
    template <typename serialiser_t>
    void serialise_deserialise(serialiser_t& serialiser_deserialiser)
    { // MY TYPE HAS THIS FUNCTION SO I WAS HOPING IT WOULD BE RECOGNIZED
    }
};

int main() {
    serialiser_deserialiser<true> serialiser_obj;
    MySerializableType serializable_type;
    serialiser_obj.read_or_write(serializable_type);
}

原因分析

  • 模板成员函数的地址无法直接推导:U::serialise_deserialise是模板成员函数,编译器无法从&U::serialise_deserialise直接确定具体的实例化版本,必须显式指定模板参数才能获得有效的函数指针。
  • 成员函数调用的参数缺失:成员函数指针的调用需要两个核心要素:对象实例(U&)和函数参数(serialiser_deserialiser&)。修改后的std::is_invocable_v只传入了函数参数类型,缺少调用成员函数必须的U对象实例,导致检测逻辑不成立。

修复方案

方案1:修正std::is_invocable的参数

显式指定模板成员函数的实例,并补充调用所需的对象参数:

constexpr bool bDoesTypeHaveSerialiseDeserialiseFunction = 
    std::is_invocable_v<decltype(&U::template serialise_deserialise<serialiser_deserialiser>), 
                        U&, 
                        serialiser_deserialiser&>;

这里的U&是调用成员函数的对象实例,serialiser_deserialiser&是函数的参数类型,完全符合成员函数指针的调用规则。

方案2:使用C++20 requires表达式(更直观)

C++20的requires表达式可以直接检测表达式是否合法,无需处理成员函数指针的复杂语法:

constexpr bool bDoesTypeHaveSerialiseDeserialiseFunction = 
    requires(U& obj, serialiser_deserialiser& ser) {
        obj.serialise_deserialise(ser);
    };

这种方式直接模拟了函数调用的场景,编译器会自动推导模板成员函数的参数,代码可读性更强。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 08:20:54