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

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-08 19:23:19

问题


My SFINAE code using std::enable_if compiles in GCC & Clang, but not in MSVC 2013.

The code (also available on cpp.sh) is

#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;
}

In GCC/Clang, this works perfectly, in MSVC though, I get:

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

The compiled and run output should be:

0 additional inputs
1 additional inputs

I've seen some similar issues on SO, but none had a clear answer or were slightly tangental.

Reading the MSVC enable_if page, this should work...

How can I use SFINAE in MSVC2013?

UPDATE

Just as a note, this does work in the positive case. For instance, if I comment out the first function, and the call to it, then the rest compiles. i.e. the enable_if<true, void> on CallDoDataProcessing does have a type member.

However, commenting out the second function and call to it (so, leaving the version where sizeof...(AdditionalInputs) == 0 does not work though. Same error.

This suggests that the sizeof...(AdditionalInputs) == 0 call is not being matched, but I can't figure out why it wouldn't be.


回答1:


Try tag dispatching.

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 is really badly supported by MSVC. Your code looks like valid SFINAE. The fact that MSVC fails to do the right thing is not surprising.

MSVC works much much better with tag dispatching in my experience, and I find it even results in easier to understand code and even error messages sometimes.

What it does not permit is noticing "no, you cannot do this" before the body of the calling function, to make the calling function also state "no, I cannot be done".



来源:https://stackoverflow.com/questions/39579182/msvc-2013-type-is-not-a-member-of-stdenable-iffalse-void

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!