我试图使用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();
}
预期的(和msvcs)行为是,调用其enable_if_t条件等于false的函数会导致编译时错误,或者如果示例中存在重载函数,则将候选函数删除以解决重载。在所有其他情况下,代码应正常编译。
另一方面,gcc告诉我在func2模板中的enable_if_t的“ struct std :: enable_if <false,void>”中找不到名为“ type”的类型,这与名为“如果条件等于true,则仅在enable_if中存在“类型”。但是,这不是SFINAE功能的理想行为吗?编译器是否应该忽略func2,因为它从未被调用过?
我现在有三个问题:
由于两个编译器产生不同的行为,它是未定义的吗?如果是,则哪些部分/语句是未定义的?
SFINAE是否适合实现我的目标,还是我误解了它的用例?
通过使用静态断言作为替代,我会更好吗?
我很抱歉,如果这个问题是一个重复的这一个,但我不认为答案有提供与我的问题有很大帮助。
海湾合作委员会是正确的。这是因为您没有将SFINAE用于您的功能。您这样做似乎是因为您使用了标准库中的SFINAE实用程序,但是这里缺少关键要素。
“ SFINAE”中的“ S”代表替代。将模板参数替换为我们要实例化的模板的参数。现在,有问题的模板是func2
。为了使SFINAE正常工作,func2
必须使用的参数替换其参数。但在这里
std::enable_if_t<B_VAL == B::VARIANT2>
没有正在func2
使用的参数。它不依赖于替换为期间发生的任何事情func2
。这只是一个无效类型,完全独立于实际实例化的尝试func2
。
虽然不难修复
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;
}
现在,检查是针对将其替换为正确的模板。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句