2016-12-11 30 views
2

我有一个班级模板Bird与布尔模板参数can_fly。根据该值,我想启用一个签名为void fly();的成员函数。如何使用SFINAE和无效成员函数?

这是我的代码:

#include <type_traits> 

template<bool can_fly> 
class Bird { 
public: 
    template<typename void_t = typename std::enable_if<can_fly>::type> 
    void_t fly() { /* ... */ } 
}; 

int main() { 
    Bird<true> flyingBird; 
    flyingBird.fly(); 
    Bird<false> flightlessBird; 

    return 0; 
} 

此代码编译在Visual Studio 2015年很好,但海湾合作委员会抱怨说,有“没有类型命名为‘结构的std :: enable_if’‘类型’”在第三行main

我认为在false案例中没有::type这个事实是SFINAE的整个观点。有人可以向我解释我做错了什么,正确的做法是什么?

回答

1

由于mentioned in this answer

enable_if工作,因为模板参数的替代,导致一个错误,并且使替代从重载决议设定的下降,只有其他可行的重载被编译器考虑。

在你的情况下没有替换,因为can_fly在实例化时已知。您可以创建一个虚拟默认模板bool参数来使SFINAE正常工作:

template<bool can_fly> 
class Bird { 
public: 
    template<bool X = can_fly, typename = typename std::enable_if<X>::type> 
    void fly() { /* ... */ } 
}; 

wandbox example

+1

现在我明白了!在我的代码中,可以在重载解析之前评估整个表达式“std :: enable_if :: type”并导致错误。而在你的代码中,表达式'std :: enable_if :: type'只能在知道'X'后才能被评估。非常感谢! –

+1

upvoted,但在生产代码中,您还需要'enable_if'中的'X == can_fly'。这禁止调用'鸟 :: fly ();'..你也可以使用'...'和'_t'来避免'typename'并缩短符号有点像'template ...> void fly(){}'。 – TemplateRex

相关问题