Home > Blockchain >  C template argument deduction for pointers to overloaded member function
C template argument deduction for pointers to overloaded member function

Time:10-18

I'm currently working on a template function that deals with pointers to member functions. It originally looked like this:

template <typename C, typename RT, typename... P>
auto CreateTestSuite(RT(C::* pFunc)(P...))
{...}

However, I soon found that if I try to pass to it a pointer to a const member function, the template will not recognize this. So I then added this overloaded version:

template <typename C, typename RT, typename... P>
auto CreateTestSuite(RT(C::* pFunc)(P...) const)
{...}

For two different member functions with const and non-const respectively, it works fine. However, if I try to call CreateTestSuite for a pointer to an overloaded member function, a problem arises.

For example, assume I have the following class A:

class A
{
public:
    return_type test(...) {...}
    return_type test(...) const {...}
};

And now when I try to make the function call

CreateTestSuite(&A::test);

The compiler will not be able to tell which overloaded version I am using. In addition, this problem cannot be solved by explicitly specifying the template arguments, because they are the same for the overloaded versions of CreateTestSuite.

How do I explicitly select from the two versions?

Edit: I can accept minor modification to CreateTestSuite.

Many thanks.

CodePudding user response:

You can add an additional template bool to CreateTestSuite() to decide whether to choose const-qualified member functions:

#include <type_traits>

template <bool IsConst = false, typename C, typename RT, typename... P>
auto CreateTestSuite(RT(C::* pFunc)(P...), std::enable_if_t<!IsConst>* = nullptr)
{ }

template <bool IsConst, typename C, typename RT, typename... P>
auto CreateTestSuite(RT(C::* pFunc)(P...) const, std::enable_if_t<IsConst>* = nullptr)
{ }

Then you can explicitly specify IsConst to call CreateTestSuite():

CreateTestSuite(&A::test);
CreateTestSuite<true>(&A::test);
CreateTestSuite<false>(&A::test);

Demo.

CodePudding user response:

As your issue is just to select the right overload, you might write helpers:

template <typename C, typename RT, typename... P>
constexpr auto non_const_overload(RT (C::*pFunc)(P...)) { return pFunc; }

template <typename C, typename RT, typename... P>
constexpr auto const_overload(RT (C::*pFunc)(P...) const) { return pFunc; }

With usage

CreateTestSuite(non_const_overload(&A::test));
CreateTestSuite(const_overload(&A::test));

Demo

Note: You might need 24 helpers to handle all combinations with volatile, reference to this and C-ellipsis.

  • Related