1

I am trying to make a kind of a "has_member". Using Clang (for msvc) it works good (I get 0, 1), but using MSVC it does not (I get 1, 1).

Here is my code

template<typename T>
using void_t = void;

namespace detail {
    template<typename AlwaysVoid, template<typename...> typename Operator, typename ...Args>
    struct _is_valid : std::false_type {};


    template<template<typename...> typename Operator, typename ...Args>
    struct _is_valid<void_t<Operator<Args...>>, Operator, Args...> : std::true_type { using type = Operator<Args...>; };
}

template<template<typename ...> typename Operator, typename ...Args>
using is_valid = detail::_is_valid<void, Operator, Args...>;

template<typename T>
using _has_push_back = decltype(std::declval<T>().push_back(std::declval<typename T::value_type>()));

template<typename T>
using has_push_back = is_valid<_has_push_back, T>;

int main() {
    std::cout << has_push_back<float>::value  << " " << has_push_back<std::vector<float>>::value << std::endl;

    getchar();
    return 0;
}

IMHO, Operator<Args...> does not fail in detail::_is_valid. But I do not understand how to make it valid for MSVC.

I am using Visual Studio 2017

Antoine Morrier
  • 3,930
  • 16
  • 37

2 Answers2

3

Visual Studio is terrible at SFINAE. Even though they claim to have improved the situation, most if not all SFINAE code I write (although it's not much) fails to work or even compile even though Clang and GCC handle the same code just fine.

Send all the failing code to Microsoft so you have a bigger chance of getting it fixed.

rubenvb
  • 74,642
  • 33
  • 187
  • 332
3

You should try:

template<typename T> struct make_void {
    using type = void;
};

template<typename T>
using void_t = typename make_void<T>::type;

The information on is_detected might also help.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • This void_t works. But I do not understand why this implementation is better than the other (that worked until now in my simple cases). This new void_t is better because he "ensure" the use of "T"? – Antoine Morrier Jul 12 '17 at 22:06
  • `::type` force the SFINAE, and there was a change/defect to support the simple alias for `void_t` in standard. – Jarod42 Jul 12 '17 at 22:11