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

为何typeid无法处理带尾部const的函数类型?

问题分析与解决

报错原因

你说得没错:非成员函数类型不能带有const限定符,void () const是一个无效的类型,这就是编译器报错的直接原因。

为什么会生成这种无效类型?

你的模板remove_ptr_to_member在处理成员函数指针decltype(&container::func)时,把它拆成了两部分:

  • 主模板的T被推导为void () const(因为成员函数指针的形式是T class_t::*,这里的T就是成员函数的"裸类型",包含它的const限定)
  • class_t被推导为container

特化版本直接把T作为type的类型,于是就生成了void () const这个非法的非成员函数类型。

解决方法:移除成员函数类型的const限定

需要修改模板,专门处理带const限定的成员函数指针,将const从函数类型中剥离,生成合法的非成员函数类型。有两种常见方式:

方式1:针对带const的成员函数指针做特化

直接修改你的模板,新增针对const成员函数指针的特化:

template <typename T, typename class_t>
struct remove_ptr_to_member { using type = T; };

// 处理普通成员函数指针
template <typename R, typename class_t, typename... Args>
struct remove_ptr_to_member<R(class_t::*)(Args...), class_t> { 
    using type = R(Args...); 
};

// 处理带const的成员函数指针
template <typename R, typename class_t, typename... Args>
struct remove_ptr_to_member<R(class_t::*)(Args...) const, class_t> { 
    using type = R(Args...); 
};

class container {
public:
    void func() const;
};

void print_member_type() {
    std::cout << typeid(typename remove_ptr_to_member<decltype(&container::func), container>::type).name() << '\n';
}

方式2:新增移除函数cv限定的辅助模板

如果需要处理更多cv限定(比如volatile、const volatile),可以先定义一个辅助模板来剥离函数类型的cv限定:

// 辅助模板:移除函数类型的cv限定符
template<typename Func>
struct remove_function_cv;

// 处理const函数
template<typename R, typename... Args>
struct remove_function_cv<R(Args...) const> {
    using type = R(Args...);
};

// 处理volatile函数
template<typename R, typename... Args>
struct remove_function_cv<R(Args...) volatile> {
    using type = R(Args...);
};

// 处理const volatile函数
template<typename R, typename... Args>
struct remove_function_cv<R(Args...) const volatile> {
    using type = R(Args...);
};

// 原模板修改
template <typename T, typename class_t>
struct remove_ptr_to_member { using type = T; };

template <typename T, typename class_t>
struct remove_ptr_to_member<T class_t::*, class_t> { 
    using type = typename remove_function_cv<T>::type; 
};

class container {
public:
    void func() const;
};

void print_member_type() {
    std::cout << typeid(typename remove_ptr_to_member<decltype(&container::func), container>::type).name() << '\n';
}

两种方式都能将type的类型修正为合法的void(),让typeid可以正常处理,编译通过。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 16:06:26