Eric Johnson
Eric Johnson

Reputation: 826

In C++-17, how to detect the existence of a templated static member function at compile time

I have a templated function (Process) where I would like to perform a compile time check to see if the supplied typename (Z) has a templated static member function taking arguments of the two supplied types (X) and (Y).

Is it possible to do this with an if constexpr test and if so, what would it be?

#include <iostream>

struct A { template<typename X, typename Y> static bool compare(const X&, const Y&) { return true; } };
struct B { };

template <typename Z, typename X, typename Y>
inline void Process(X x, Y y)
{    
    if constexpr (std::is_invocable_v<decltype(Z::compare), const X&, const Y&> )
    {
        Z::compare(x,y);
    }
    else { 
        std::cout << "hi";
    }
}

int main()
{
    Process<A>(3,2);
    Process<B>(3,2);    
}

Upvotes: 1

Views: 157

Answers (1)

Igor Tandetnik
Igor Tandetnik

Reputation: 52621

I can't think of a way to do it with if constexpr alone, without a pair of overloads to test with SFINAE. See if something like this works for you:

template <typename Z, typename X, typename Y>
auto test(X x, Y y) ->
    std::enable_if_t<sizeof(decltype(Z::compare(x, y))*) != 0, std::true_type>;

template <typename Z>
std::false_type test(...);

template <typename Z, typename X, typename Y>
inline void Process(X x, Y y)
{    
    if constexpr (decltype(test<Z>(x, y))::value)
    {
        Z::compare(x,y);
    }
    else { 
        std::cout << "hi";
    }
}

Demo.

This doesn't test that Z has a templated member function specifically, just that it has a static member function with the right name callable with the right arguments.

Upvotes: 1

Related Questions