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

C++03环境下如何从模板类中剔除针对void类型的函数

在C++03中为智能指针模板类剔除void类型的operator*函数

要在C03中实现仅针对非void类型保留operator*,同时避免全类特化,可以利用SFINAE结合函数模板参数推导(避开C03不支持函数模板默认参数的限制),具体实现如下:

核心思路

  1. 保留原有的EnableIfNotVoid特性模板,用于在T为void时禁用类型定义。
  2. 将operator*改为函数模板,通过参数推导绑定U与类模板参数T,同时利用SFINAE在U为void时剔除该函数。

完整代码示例

template<typename T> struct EnableIfNotVoid { typedef T type; };
template<> struct EnableIfNotVoid<void> {};

template<typename T> class SmartPtr
{
public:
    // 利用参数推导绑定U与T,无需函数模板默认参数
    template<typename U>
    typename EnableIfNotVoid<U>::type& operator*(U* = content) const
    {
        return *content;
    }

private:
    T* content;
};

int main(int, char **)
{
    SmartPtr<int> works;
    SmartPtr<void> noWork;
    int& i = *works; // 正常编译
    // *noWork; // 编译报错,符合预期:无匹配的operator*
}

方案解释

  • 当调用*works时,编译器会推导U为int(因为content是int*),此时EnableIfNotVoid<int>::type有效,函数正常参与重载决议并生成。
  • 当T为void时,推导U为void,EnableIfNotVoid<void>没有定义type,根据SFINAE规则,该函数模板会被从重载候选中剔除,不会引发编译错误,同时SmartPtr<void>也就没有可用的operator*。
  • 该方案无需全类特化,仅针对单个函数做处理,符合你的需求。

为什么之前的方案失败

  1. 移除默认参数:函数模板无法推导U的类型,导致找不到匹配的operator*。
  2. 移除函数模板:类实例化时会直接检查返回类型,EnableIfNotVoid<void>::type不存在会直接报错,SFINAE无法生效(SFINAE仅作用于模板函数的重载决议阶段)。
  3. 不使用SFINAE:直接返回T&会在T=void时触发“形成void引用”的编译错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 10:05:12