Antoine Morrier
Antoine Morrier

Reputation: 4078

MSVC SFINAE: Substitution does not fail

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

Upvotes: 1

Views: 402

Answers (2)

Jarod42
Jarod42

Reputation: 217135

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.

Upvotes: 3

rubenvb
rubenvb

Reputation: 76519

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.

Upvotes: 3

Related Questions