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

带默认参数的SFINAE在MSVC可编译,GCC/Clang不行,求标准判定

标准判定:MSVC与GCC/Clang在SFINAE场景下的行为正确性

我学习C++的SFINAE技术后编写了一段程序,该程序可在MSVC中正常编译运行,但无法通过GCC和Clang的编译。

程序代码如下:

#include <iostream>
#include <type_traits>

struct C1{
    enum{
        c1 = 1
    };
};

struct C2{
    enum{
        c2 = 5
    };
};

template<class C>
class entity{
    void func1(){std::cout << "func1 called";} 
    void func2(){std::cout << "func2 called ";}
public:
    template<typename T = C>void common(bool b = std::is_same<T, C1>::value && std::is_enum<decltype(T::c1)>::value)
    {
        func1();
    }
        
    template<typename T = C>void common(int, bool b = std::is_same<T, C2>::value && std::is_enum<decltype(T::c2)>::value)
    {
        func2();
    }
    template<typename... T>
    void common(T...)
    {
        std::cout <<" General version " << std::endl;
    } 

}; 
int main()
{

    entity<C2> e;
    e.common(); //works with msvc but not with gcc and clang
    
}

调用e.common()时,MSVC可正常处理,但GCC报错如下:

In member function 'void entity<C>::common(bool) [with T = C2; C = C2]':
<source>:21:102: error: 'c1' is not a member of 'C2'
   21 |     template<typename T = C>void common(bool b = std::is_same<T, C1>::value && std::is_enum<decltype(T::c1)>::value)
      |                                                                                                      ^
<source>:41:13: note:   when instantiating default argument for call to 'void entity<C>::common(bool) [with T = C2; C = C2]'
   41 |     e.common(); //works with msvc but not with gcc and clang
      |     ~~~~~~~~^~

标准判定结论

GCC和Clang的行为符合C++标准,MSVC的行为不符合标准。

依据C++标准,SFINAE(替换失败并非错误)仅适用于函数模板的模板参数推导阶段:当推导模板参数时,若替换模板参数到函数的签名(返回类型、参数类型)中出现无效构造,会将该候选函数从重载集中排除,而非引发编译错误。

但函数模板的默认参数的实例化并不属于SFINAE的适用范围:在本例中,调用e.common()时,第一个common模板的模板参数T会被推导为C2,此时需要实例化该函数的默认参数表达式std::is_same<T, C1>::value && std::is_enum<decltype(T::c1)>::value,其中decltype(T::c1)在T=C2时是非法的(C2没有c1成员)。这个错误发生在模板参数推导完成之后,属于默认参数的实例化错误,会直接引发编译错误,而非通过SFINAE排除该候选函数。因此GCC和Clang的报错是符合标准要求的,MSVC允许该代码编译的行为不符合标准。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 08:55:23