简体   繁体   English

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

[英]C++ template argument deduction for pointers to overloaded member function

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.但是,我很快发现,如果我尝试将指向 const 成员函数的指针传递给它,模板将无法识别这一点。 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.对于分别具有 const 和非常量的两个不同成员函数,它工作正常。 However, if I try to call CreateTestSuite for a pointer to an overloaded member function, a problem arises.但是,如果我尝试调用CreateTestSuite以获得指向重载成员函数的指针,则会出现问题。

For example, assume I have the following class A:例如,假设我有以下 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 .此外,这个问题不能通过显式指定模板参数来解决,因为它们对于CreateTestSuite的重载版本是相同的。

How do I explicitly select from the two versions?如何从两个版本中明确选择?

Edit: I can accept minor modification to CreateTestSuite .编辑:我可以接受对CreateTestSuite微小修改。

Many thanks.非常感谢。

You can add an additional template bool to CreateTestSuite() to decide whether to choose const -qualified member functions:您可以向CreateTestSuite()添加一个额外的模板bool来决定是否选择const限定成员函数:

#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() :然后您可以显式指定IsConst来调用CreateTestSuite()

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

Demo.演示。

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.注意:您可能需要 24 个助手来处理所有与volatile组合,参考 this 和 C-ellipsis。

or MACRO (with c++20 lambda immediate-called):或 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演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM