指向重载成员函数的指针的 C++ 模板参数推导

C++ template argument deduction for pointers to overloaded member function

我目前正在研究处理指向成员函数的指针的模板函数。它最初看起来像这样:

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

但是,我很快发现,如果我尝试向它传递一个指向常量成员函数的指针,模板将无法识别。所以我然后添加了这个重载版本:

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

对于分别具有 const 和非常量的两个不同成员函数,它工作正常。但是,如果我尝试为指向重载成员函数的指针调用 CreateTestSuite,就会出现问题。

例如,假设我有以下 class A:

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

现在当我尝试调用函数时

CreateTestSuite(&A::test);

编译器将无法判断我使用的是哪个重载版本。此外,这个问题不能通过显式指定模板参数来解决,因为它们对于 CreateTestSuite.

的重载版本是相同的

如何从两个版本中显式select?

编辑: 我可以接受对 CreateTestSuite.

的微小修改

非常感谢。

您可以在CreateTestSuite()中添加一个额外的模板bool来决定是否选择[=​​14=]限定的成员函数:

#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)
{ }

然后可以显式指定IsConst来调用CreateTestSuite():

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

Demo.

由于您的问题只是 select 正确的过载, 你可以写助手:

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; }

随着使用

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

Demo

注意:您可能需要 24 个助手来处理所有带有 volatile 的组合,请参考此和 C-ellipsis。

或 MACRO(使用 c++20 lambda 立即调用):

#define OVERLOAD(name, /*qualifiers*/...) []<typename C, typename RT, typename... P>(RT (C::*pFunc)(P...) __VA_ARGS__){ return pFunc; }(name)
CreateTestSuite(OVERLOAD(&A::test)); /*no const*/
CreateTestSuite(OVERLOAD(&A::test,)); /*no const*/
CreateTestSuite(OVERLOAD(&A::test, const));

Demo