MSVC 2013 'type': 不是 'std::enable_if<false,void> 的成员

MSVC 2013 'type' : is not a member of 'std::enable_if<false,void>

我使用 std::enable_if 的 SFINAE 代码可以在 GCC 和 Clang 中编译,但不能在 MSVC 2013 中编译。

代码(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/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 上看到过一些类似的问题,但是 none 有一个明确的答案或者有点切题。

正在阅读 MSVC enable_if 页面,这应该可行...

如何在 MSVC2013 中使用 SFINAE?

更新

请注意,这在肯定的情况下确实有效。例如,如果我注释掉第一个函数和对它的调用,那么其余的都会编译。即 CallDoDataProcessing 上的 enable_if<true, void> 确实有一个 type 成员。

但是,注释掉第二个函数并调用它(因此,保留 sizeof...(AdditionalInputs) == 0 不起作用的版本。同样的错误。

这表明 sizeof...(AdditionalInputs) == 0 调用不匹配,但我不明白为什么不匹配。

尝试标签调度。

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 在标记分派方面好得多,我发现它甚至可以使代码更容易理解,有时甚至会产生错误消息。

它不允许的是在调用函数的主体之前注意 "no, you cannot do this",使调用函数也状态为 "no, I cannot be done".