我的SFINAE代码使用std::enable_if
编译在GCC& Clang,但不是在MSVC 2013中。
#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 / Clang中,这很有效,但在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页面,这应该有用......
如何在MSVC2013中使用SFINAE?
更新
就像一张纸条,这确实适用于积极的情况。例如,如果我注释掉第一个函数,并调用它,那么其余函数就会编译。即enable_if<true, void>
上的CallDoDataProcessing
确实有type
成员。
然而,注释掉第二个函数并调用它(所以,将版本保留在sizeof...(AdditionalInputs) == 0
不起作用。相同的错误。
这表明sizeof...(AdditionalInputs) == 0
来电未被匹配,但我无法弄清楚它为什么不会。
答案 0 :(得分:7)
尝试标记调度。
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未能做正确的事情并不令人惊讶。
根据我的经验,MSVC使用标签调度更好地工作 ,我发现它甚至会导致更容易理解代码甚至错误消息。它不允许的是在调用函数体之前注意“不,你不能这样做”,使调用函数也说“不,我不能完成”。