1

Is the following code legal C++11?

#include <type_traits>

template<typename T>
typename std::enable_if<T::Data() == nullptr>::type test (T t)
{
  static_assert (t.Data() == nullptr, "pData is not null");
}

template<typename T>
typename std::enable_if<T::Data() != nullptr>::type test (T t)
{
  static_assert (t.Data() != nullptr, "pData is not null");
}

clang compiles it without error, but MSVC generates the following error message:

error C2995: 'std::enable_if<,void>::type test(T)': function template has already been defined
note: see declaration of 'test'

How should I rewrite the above code to let it compile on the common C++ compilers (GCC, Clang, MSVC)?

m7913d
  • 10,244
  • 7
  • 28
  • 56
  • 1
    Looks like an MSVC bug. Can you submit it? Oddly, if you change it to `T::Data` instead of `T::Data()`, it [gets accepted](https://godbolt.org/z/J_CBjV)? That shouldn't matter. – Barry Nov 25 '19 at 17:54
  • @barry, Ok, thanks for confirming it is a bug (and reopening the question). Where should I submit it? I'm not familiar with MSVC bug reports. Do you know a workaround (without changing `T::Data()` to `T::Data` as it is part of an external library) – m7913d Nov 25 '19 at 18:08
  • I'm not either, but they should have some kind of bug report system. – Barry Nov 25 '19 at 18:26
  • I created a bug report [here](https://developercommunity.visualstudio.com/content/problem/833543/function-template-has-already-been-defined-using-s.html) – m7913d Nov 25 '19 at 20:28

1 Answers1

0

According to @Barry, the code is legal C++11 (it compiles using GCC and Clang).

So, it's a bug of MSVC. I created a bug report in the developer community.

Update: Microsoft has fixed this bug: downloading the latest msvc should resolve this issue, as stated in the bug report.

A workaround (if you are unable to use the latest msvc) is to use a helper class derived from std::integral_constant:

template<typename T>
class IsDataNull : public std::integral_constant<bool, T::Data() == nullptr> {};

template<typename T>
typename std::enable_if<IsDataNull<T>::value>::type test (T t)
{
  static_assert (t.Data() == nullptr, "pData is not null");
}

template<typename T>
typename std::enable_if<!IsDataNull<T>::value>::type test (T t)
{
  static_assert (t.Data() != nullptr, "pData is not null");
}
m7913d
  • 10,244
  • 7
  • 28
  • 56