指向重载成员函数的指针的 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);
由于您的问题只是 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));
注意:您可能需要 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));
我目前正在研究处理指向成员函数的指针的模板函数。它最初看起来像这样:
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);
由于您的问题只是 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));
注意:您可能需要 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));