Search code examples
c++templatessfinaedecltype

How to properly apply decltype together with SFINAE?


I wrote a template wrapper that should find out if the class owns the function.

template<typename...>
using void_t = void;

template <typename ,typename = void>
struct has_member:std::false_type{};

template<typename T>
struct has_member<T, void_t<decltype(std::declval<T>().push_back())>>:std::true_type{};

But I can't figure out how to apply it correctly.I tried at first like this:

template<typename T, bool = has_member<T>::value>
void foo(T& container) {
    std::cout << "i here";
}

But everything goes there, i.e. even if there is no push_back function:

std::set<int> st;
foo(st); // okey

Tried to change to:

template<typename T,typename std::enable_if_t< has_member<T>::value ,int>* = nullptr >
void foo(T& container) {
    std::cout << "i here";
}

But together with such a function call

std::vector<int> vc(10);
foo(vc);

I get a few errors:

Error (active)  E0304   no instance of function template "foo" matches the argument list    
Error   C2672   'foo': no matching overloaded function found    
Error   C2783   'void foo(T &)': could not deduce template argument for '__formal'  

I'd happy some help to figure out what I did wrong .

Also. Can all structures be replaced with?

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

I also did not get an insert in the function (with the same errors as above)


Solution

  • I use a vector there and expected that it will pass

    The problem is in std::declval<T>().push_back(), there's no push_back taking nothing for std::vector.

    You need to pass argument to push_back, e.g.

    template<typename T>
    struct has_member<T, void_t<decltype(std::declval<T>().push_back(std::declval<typename T::value_type>()))>>:std::true_type{};
    

    LIVE

    And about why the 1st solution doesn't work, because when has_member<T>::value is true, the instantiation foo<T, true> gets called, otherwise foo<T, false> gets called, both are valid.