【问题标题】:C++ template argument deduction for pointers to overloaded member function指向重载成员函数的指针的 C++ 模板参数推导
【发布时间】:2021-10-18 07:02:26
【问题描述】:

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

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

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

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

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

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

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

现在当我尝试调用函数时

CreateTestSuite(&A::test);

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

如何从两个版本中明确选择?

编辑: 我可以接受对CreateTestSuite 的细微修改。

非常感谢。

【问题讨论】:

  • 带铸造CreateTestSuite( static_cast&lt;return_type (A::*)(...) /*const*/&gt;(&amp;A::test) );
  • @rafix07 感谢您的建议。但这对我来说不是很满意。如果 A::test 的参数列表很长,那我就得写很多了。
  • 恐怕除了强制转换之外别无他法。您能否解释一下,作为人类,您想如何区分CreateTestSuite(&amp;A::test) 此处写的内容?你会期待什么超载?
  • 对不起,我对这个问题的描述可能不是很清楚。我可以接受对CreateTestSuite 的细微修改。
  • 你不能用std::function吗?

标签: c++ templates overloading


【解决方案1】:

您可以在CreateTestSuite()中添加一个额外的模板bool来决定是否选择const-qualified成员函数:

#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.

【讨论】:

    【解决方案2】:

    由于您的问题只是选择正确的重载, 你可以写助手:

    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 的所有组合,参考 this 和 C 省略号。

    或 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

    【讨论】:

    • @Const:我必须等待其他用户:Volatile、Cellipsis、... ;-)
    • @Const:带有立即调用 lambda 的 MACRO 可能会完成这项工作(添加了示例),但我一般更喜欢避免使用 MACRO。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多