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);
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));
Note: You might need 24 helpers to handle all combinations with volatile
, reference to this and C-ellipsis.