'std::enable_if based on expression using static constexpr member function

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)?



Solution 1:[1]

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");
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1