C++ 在尝试使用SFINAE禁用函数时,我是否创建了未定义的行为?

C++ 在尝试使用SFINAE禁用函数时,我是否创建了未定义的行为?,c++,gcc,visual-c++,undefined-behavior,sfinae,C++,Gcc,Visual C++,Undefined Behavior,Sfinae,我试图使用SFINAE基于一些非模板化枚举参数禁用类的某些函数 下面的代码不使用gcc编译,但在使用msvc编译器时,似乎可以按照预期编译和工作 #include <iostream> #include <type_traits> enum class B { VARIANT1, VARIANT2 }; template<B B_VAL> struct A { template<class = std::enable_if_t<B_VA

我试图使用SFINAE基于一些非模板化枚举参数禁用类的某些函数

下面的代码不使用gcc编译,但在使用msvc编译器时,似乎可以按照预期编译和工作

#include <iostream>
#include <type_traits>

enum class B { VARIANT1, VARIANT2 };

template<B B_VAL>
struct A {
    template<class = std::enable_if_t<B_VAL == B::VARIANT1>>
    void func1() {
        std::cout<<"VARIANT1"<<std::endl;
    }
    template<class = std::enable_if_t<B_VAL == B::VARIANT2>>
    void func2() {
        std::cout<<"VARIANT2"<<std::endl;
    }
};

int main()
{
    A<B::VARIANT1> a;
    a.func1();
}
#包括
#包括
枚举类B{VARIANT1,VARIANT2};
模板
结构A{
模板
void func1(){

std::coutGCC是正确的。这是因为您没有将SFINAE用于您的函数。您这样做可能是因为您使用了标准库中的SFINAE实用程序,但这里缺少一个关键要素

“SFINAE”中的“S”代表替换。将模板参数替换为我们试图实例化的模板的参数。现在,所讨论的模板是
func2
。要使SFINAE正常工作,必须用
func2
的参数替换它的参数。但是这里

std::enable_if_t<B_VAL == B::VARIANT2>

现在,检查是将替换替换成正确的模板。

非常感谢工作中的力学的伟大回答和解释,但是这是否意味着MSVC偏离标准C++?@ JavaFunFo-98-是的。模板的MSVC实现已经臭名昭著多年。例如,它们不支持两阶段查找。直到大约两年前,甚至到那时,只有在选择更符合标准时。
template<B B_VAL_ = B_VAL, class = std::enable_if_t<B_VAL_ == B::VARIANT1>>
void func1() {
    std::cout<<"VARIANT1"<<std::endl;
}

template<B B_VAL_ = B_VAL, class = std::enable_if_t<B_VAL_ == B::VARIANT2>>
void func2() {
    std::cout<<"VARIANT2"<<std::endl;
}