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

使用std::is_base_of实现类SFINAE开关在GCC/Clang编译报错

问题原因

你的SFINAE写法不符合C++标准要求,MSVC属于非标准兼容才允许了你的原有逻辑:
SFINAE机制仅对模板即时上下文中的错误生效,你原有代码中std::is_base_of<QWidget, cls>::value的判定对象cls是外层Wrapper类的模板参数,不属于当前style成员函数模板的即时上下文。当外层Wrapper类用QLayout子类实例化时,编译器会直接检查style函数的函数体,发现setStyleSheet不存在就直接报错,不会触发SFINAE淘汰该函数。

解决方案

方案1:兼容C++11的写法(改动最小)

给成员函数模板新增一个默认值为cls的本地模板参数,让enable_if的判定依赖当前函数模板的参数,即可触发SFINAE:

template<typename T = cls, typename = typename std::enable_if<std::is_base_of<QWidget, T>::value>::type>
Wrapper &style(const QString &stylesheet) {
    cast()->setStyleSheet(stylesheet);
    return *this;
}

该写法和你原有逻辑几乎一致,不需要拆分两套代码,直接替换原有模板声明即可,GCC/Clang均可正常编译。

方案2:C++20及以上简化写法

直接用C++20的requires约束,写法更简洁:

Wrapper &style(const QString &stylesheet) requires std::is_base_of_v<QWidget, cls> {
    cast()->setStyleSheet(stylesheet);
    return *this;
}

无需额外定义模板参数,编译器会自动在重载决议阶段淘汰不符合约束的函数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 14:15:05