Oragon Efreet
Oragon Efreet

Reputation: 1134

Using SFINAE to check for member function and call it

I am trying to understand how SFINAE works.

My needs:

I have a set of types which may provide or not a member function called activate. The thing is if activate does exist for the given type, it may accept any arguments. I want to write a function that will forward to the type's activate, if it exists, otherwise simply return true.

I tried:

#include <iostream>
#include <utility>
#include <functional>

struct A
{
    bool activate()
    {   
        std::clog << "A::activate() called" << std::endl;
        return true;
    }   

    bool activate(const char*)
    {   
        std::clog << "A::activate(const char*) called" << std::endl;
        return true;
    }   
};

struct B
{
    // NOTHING
};

template<class S, class... ARGS>
auto activate(S& s, ARGS&&... p_args) -> typename std::invoke_result<decltype(&S::activate)(S, ARGS...)>::type
{
    return s.activate(std::forward<ARGS>(p_args)...);
}

bool activate(...)
{
    return true;
}


int main(int argc, char* argv[])
{
    A a;
    B b;

    activate(a);
    activate(a, "Hello");
    activate(b);

    return 0;
}

But nothing is ever printed. Why?

Upvotes: 2

Views: 666

Answers (1)

Barry
Barry

Reputation: 303107

Your problem is here:

template<class S, class... ARGS>
auto activate(S& s, ARGS&&... p_args)
    -> typename std::invoke_result<decltype(&S::activate)(S, ARGS...)>::type
//                                          ^^^^^^^^^^^^

If activate is an overloaded member function, as it is for A, you can't take its address via decltype. Secondly, that's an incorrect use of invoke_result - it doesn't use the result_of syntax of F(Args...), you just do invoke_result<F, Args...>. It's simpler.

What you want is to just directly invoke it yourself:

template<class S, class... ARGS>
auto activate(S& s, ARGS&&... p_args)
    -> decltype(s.activate(std::forward<ARGS>(p_args)...))

This side-steps the question of overloaded names, and how to use invoke_result.

Upvotes: 4

Related Questions