3

So far I've been able to detect whether a function exists in a class by name, without needing its signature, as follows:

Following piece of code heavily "inspired" by the answer from this question: Is it possible to figure out the parameter type and return type of a lambda?

I understand that different specializations should be created for different modifiers, such as const member functions.

template <typename T, typename TReturn, typename... Args>
struct function_traits<TReturn( T::* )( Args... )>
{
    using return_type = TReturn;
    using arguments = std::tuple<Args...>;

    static std::size_t constexpr arg_count = sizeof...( Args );

    template <std::size_t N, typename = void>
    struct argument
    {
        using type = std::tuple_element_t<N, arguments>;
    };

    template <std::size_t N>
    struct argument<N, std::enable_if_t<( !( N < arg_count ) ), void>> {};
};

And my own code as a workaround for 28.4.4 of The C++ Programming Language, 4th Edition since I am using VC++2015.

template <typename T>
struct has_func_f
{
private:
    template <typename C, typename = void>
    struct get_result
    {
        static bool constexpr value = false;
    };

    // need <function_name> as a class parameter so I can append and get &C::<function_name>
    template <typename C>
    struct get_result<C, std::enable_if_t<( std::is_same<decltype( ( decltype( std::declval<typename function_traits<decltype( &C::f )>::arguments>() ) ) ( std::declval<typename function_traits<decltype( &C::f )>::arguments>() ), std::true_type() ), std::true_type>::value ), void>>
    {
        static bool constexpr value = true;
    };

public:
    static bool constexpr value = get_result<T>::value;
};

This code works for detecting any function signature as long as the name matches. My example usage:

struct A {};
struct B { float f(int, double); };
struct C { void f(); };

int main()
{
    has_func_f<A>::value; // false
    has_func_f<B>::value; // true
    has_func_f<C>::value; // true

    return 0;
}

So as my question states, how can I possibly do what I want to do? I've looked and looked and the closest thing I've come to is using a macro to generate the appropriate struct for the function name I want. Is there any other way?

Community
  • 1
  • 1
bku_drytt
  • 3,169
  • 17
  • 19
  • I don't understand the reasoning behind this. I let the compiler and linker tell me whether a method exists or not. – Thomas Matthews Jul 26 '15 at 17:00
  • Your code is not valid C++ (it uses msvc extensions) and does not work with overloaded methods (at least at first glance). As with most of this kind of question, the answer is hack it with macros and end up with a poor solution, wait u til C++ has reflection, or don't use raw C++ types. The best answer depends on what your application is, but these type of questions are idle curiosity 99 times out of 100. – Yakk - Adam Nevraumont Jul 26 '15 at 17:02
  • The reasoning behind this code was to avoid getting compile time errors when attempting to call a function from another template class when the template parameter did not have the function. So said template class could be used with template parameters that had f() and those that didn't have f() without having compilation errors. My original motivation was actually the lack of concepts. – bku_drytt Jul 26 '15 at 17:06
  • I probably ended up using MSVC extensions without knowing because I had to look at how such functionality was implemented by VC++ for items like std::is_assignable. It doesn't work with overloaded methods because I'm only testing whether the class has a function with that name. Overloads could be targeted by a tuple template parameter containing the function parameter types. – bku_drytt Jul 26 '15 at 17:19
  • [Boost.Hana](https://github.com/ldionne/hana) uses a polymorphic lambda to write a short ad-hoc test like this: `[](auto&& p) -> decltype((void)p.f()) {}` You could similarly check `[](auto p) -> decltype(&unwrap::f) {}` Or using Yakk's variant via an alias template `template using has_f = decltype( &T::f );` – dyp Jul 26 '15 at 18:12

0 Answers0