Std:Enable_if可以有条件地编译成员函数

Std:Enable_if可以有条件地编译成员函数

我试着用一个简单的例子来理解如何使用std::enable_if..在我读完之后这个答案我认为想出一个简单的例子应该不难。我想用std::enable_if在两个成员函数之间进行选择,并且只允许其中一个被使用。

不幸的是,下面的代码没有用GCC 4.7编译,经过几个小时的尝试,我问你们我的错误是什么。

#include <utility>#include <iostream>template< class T >class Y {

    public:
        template < typename = typename std::enable_if< true >::type >
        T foo() {
            return 10;
        }
        template < typename = typename std::enable_if< false >::type >
        T foo() {
            return 10;
        }};int main() {
    Y< double > y;

    std::cout << y.foo() << std::endl;}

GCC报告了以下问题:

% LANG=C make CXXFLAGS="-std=c++0x" enable_if
g++ -std=c++0x    enable_if.cpp   -o enable_if
enable_if.cpp:12:65: error: `type' in `struct std::enable_if<false>' does not name a type
enable_if.cpp:13:15: error: `template<class T> template<class> T Y::foo()' cannot be overloaded
enable_if.cpp:9:15: error: with `template<class T> template<class> T Y::foo()'

为什么g+不删除第二个成员函数的错误实例化?根据标准,std::enable_if< bool, T = void >::type只有当布尔模板参数为真时才存在。但是为什么g+不认为这是SFINAE呢?我认为重载错误消息来自g+不删除第二个成员函数的问题,并认为这应该是过载


LEATH
浏览 1845回答 3
3回答

哔哔one

SFINAE只有当替换在参数演绎中的模板参数使构造不正确时才有效。没有这样的替代。我也是这么想的,我试着用std::is_same< T, int >::value和! std::is_same< T, int >::value结果是一样的。这是因为当类模板被实例化时(当您创建一个类型为Y<int>在其他情况下),它实例化其所有成员声明(不一定是它们的定义/主体!)。其中还包括其成员模板。请注意T就知道了,而且!std::is_same< T, int >::value结果是假的。所以它将创建一个类Y<int>其中包含class&nbsp;Y<int>&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;public: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;instantiated&nbsp;from &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;template&nbsp;<&nbsp;typename&nbsp;=&nbsp;typename&nbsp;std::enable_if<&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::is_same<&nbsp;T,&nbsp;int&nbsp;>::value&nbsp;>::type&nbsp;> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;T&nbsp;foo()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;10; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;template&nbsp;<&nbsp;typename&nbsp;=&nbsp;typename&nbsp;std::enable_if<&nbsp;true&nbsp;>::type&nbsp;> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;foo(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;instantiated&nbsp;from &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;template&nbsp;<&nbsp;typename&nbsp;=&nbsp;typename&nbsp;std::enable_if<&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;!&nbsp;std::is_same<&nbsp;T,&nbsp;int&nbsp;>::value&nbsp;>::type&nbsp;> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;T&nbsp;foo()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;10; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;template&nbsp;<&nbsp;typename&nbsp;=&nbsp;typename&nbsp;std::enable_if<&nbsp;false&nbsp;>::type&nbsp;> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;foo();};这个std::enable_if<false>::type访问不存在的类型,因此声明格式不正确。因此你的程序是无效的。您需要使成员模板‘enable_if依赖于成员模板本身的参数。那么声明是有效的,因为整个类型仍然是依赖的。当您试图调用其中之一时,它们的模板参数的参数推导就会发生,而SFINAE就会像预期的那样发生。看见这个问题以及如何做到这一点的相应答案。

DIEA

我做了这个简短的例子,这也是有效的。#include&nbsp;<iostream>#include&nbsp;<type_traits>class&nbsp;foo;class&nbsp;bar;template<class&nbsp;T>struct&nbsp;is_bar{ &nbsp;&nbsp;&nbsp;&nbsp;template<class&nbsp;Q&nbsp;=&nbsp;T> &nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;std::enable_if<std::is_same<Q,&nbsp;bar>::value,&nbsp;bool>::type&nbsp;check() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;true; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;template<class&nbsp;Q&nbsp;=&nbsp;T> &nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;std::enable_if<!std::is_same<Q,&nbsp;bar>::value,&nbsp;bool>::type&nbsp;check() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;false; &nbsp;&nbsp;&nbsp;&nbsp;}};int&nbsp;main(){ &nbsp;&nbsp;&nbsp;&nbsp;is_bar<foo>&nbsp;foo_is_bar; &nbsp;&nbsp;&nbsp;&nbsp;is_bar<bar>&nbsp;bar_is_bar; &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!foo_is_bar.check()&nbsp;&&&nbsp;bar_is_bar.check()) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;<<&nbsp;"It&nbsp;works!"&nbsp;<<&nbsp;std::endl; &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;0;}如果你想让我详细解释的话。我认为这段代码或多或少是不言自明的,但我还是这样做了,所以我可能错了:)你可以看到它的作用这里.

慕仙森

对于那些正在寻找“只起作用”的解决方案的后来者来说:#include&nbsp;<utility>#include&nbsp;<iostream>template<&nbsp;typename&nbsp;T&nbsp;>class&nbsp;Y&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;template<&nbsp;bool&nbsp;cond,&nbsp;typename&nbsp;U&nbsp;> &nbsp;&nbsp;&nbsp;&nbsp;using&nbsp;resolvedType&nbsp;&nbsp;=&nbsp;typename&nbsp;std::enable_if<&nbsp;cond,&nbsp;U&nbsp;>::type;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;public: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;template<&nbsp;typename&nbsp;U&nbsp;=&nbsp;T&nbsp;>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;resolvedType<&nbsp;true,&nbsp;U&nbsp;>&nbsp;foo()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;11; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;template<&nbsp;typename&nbsp;U&nbsp;=&nbsp;T&nbsp;> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;resolvedType<&nbsp;false,&nbsp;U&nbsp;>&nbsp;foo()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;12; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}};int&nbsp;main()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;Y<&nbsp;double&nbsp;>&nbsp;y; &nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;<<&nbsp;y.foo()&nbsp;<<&nbsp;std::endl;}汇编:g++&nbsp;-std=gnu++14&nbsp;test.cpp跑步给:./a.out&nbsp; 11
打开App,查看更多内容
随时随地看视频慕课网APP