2016-09-19 124 views
6

我SFINAE代码使用std::enable_if编译在GCC &铛,但不是在2013年MSVCMSVC 2013 '类型':不是“STD成员:: enable_if <false,void>

代码(also available on cpp.sh)是

#include <iostream> 
#include <type_traits> 

template <typename T, typename ... AdditionalInputs> 
typename std::enable_if<sizeof...(AdditionalInputs) == 0, void>::type 
CallDoDataProcessing(T var) { 
    std::cout << sizeof...(AdditionalInputs) << " additional inputs" << std::endl; 
} 

template <typename T, typename ... AdditionalInputs> 
typename std::enable_if<sizeof...(AdditionalInputs) == 1, void>::type 
CallDoDataProcessing(T var) { 
    std::cout << sizeof...(AdditionalInputs) << " additional inputs" << std::endl; 
} 

int main() { 
    CallDoDataProcessing<int>(3); 
    CallDoDataProcessing<int, int>(3); 
    return 0; 
} 

在GCC /铛,这个完美的作品,在MSVC不过,我得到:

Error 1 error C2039: 'type' : is not a member of 'std::enable_if<false,void>' c:\Users\mrussell\documents\visual studio 2013\Projects\ConsoleApplication1\ConsoleApplication1\ConsoleApplication1.cpp 5 1 ConsoleApplication1 

的编译和运行输出应为:

0 additional inputs 
1 additional inputs 

我在SO上看到过一些类似的问题,但没有一个有明确的答案,或者是略微正切的。

MSVC enable_if页面,这应该工作...

如何使用SFINAE在MSVC2013?

UPDATE

正如一个音符,这确实在积极的情况下工作。例如,如果我注释掉第一个函数和对它的调用,那么其余的就会编译。即在CallDoDataProcessing上的enable_if<true, void>确实具有type成员。

然而,注释掉第二个函数并调用它(所以,留下的版本,其中sizeof...(AdditionalInputs) == 0不工作,虽然,同样的错误。

这表明sizeof...(AdditionalInputs) == 0呼叫没有被匹配,但我可以”牛逼弄清楚为什么它不会。

+0

你是否#include '? – AndyG

+0

@AndyG从来没有想到这一点,我只是试过,但似乎没有什么区别。我将修改上面的代码以显示包含的内容。 – Matt

+1

我的第一个猜测是你需要更新MSVC –

回答

5

try标记调度。

template<std::size_t> 
struct size {}; 

namespace details { 
    template <typename T, typename ... AdditionalInputs> 
    void CallDoDataProcessing(T var, size<0>) { 
    std::cout << sizeof...(AdditionalInputs) << ", aka 0, additional inputs" << std::endl; 
    } 

    template <typename T, typename ... AdditionalInputs, std::size_t N> 
    void CallDoDataProcessing(T var, size<N>) { 
    std::cout << sizeof...(AdditionalInputs) << " additional inputs" << std::endl; 
    } 
} 
template <typename T, typename ... AdditionalInputs> 
void CallDoDataProcessing(T var) { 
    details::CallDoDataProcessing<T, AdditionalInputs>(var, size<sizeof...(AdditionalInputs)>{}); 
} 

SFINAE真的不好用MSVC的支持。你的代码看起来像有效SFINAE。这MSVC不能做正确的事的事实是n令人惊讶。

MSVC的工作原理很多更好用我的经验标签调度,我发现它甚至有时会更容易理解代码甚至错误消息。

它不允许在调用函数的主体之前注意“不,你不能这样做”,使调用函数也声明“不,我不能做”。

+0

不错!起初,我认为这也会限制我'AdditionalInputs'为0或1,但我写了一个[可用于N个输入的示例](http://cpp.sh/82nwr) – Matt

+1

@matt你回到SFINAE那里有'enable_if'的东西。再一次,MSVC并没有很好的完成SFINAE。它可以以惊人的方式从完全不相关的代码变更中解脱出来。如果你想让'N'为'1'或'2',只需要'size <1>'或'size <2>',不要拿'N',然后SFINAE说'N'应该是'1'或'2' '。如果你需要的话,留下一个处理“你的具体情况之上的所有事情”的'N'通用的。 (当然,理想的情况是通用的会处理所有情况,但是...) – Yakk

+0

好的,我明白你的意思了。我玩过它,但习惯上仍然过度依赖SFINAE。我想我终于在[这个例子]中实现了你的建议(http://cpp.sh/2bsyd) – Matt