C++ 在指向-(成员-)函数表达式的指针中解析函数重载和模板实例化

C++ 在指向-(成员-)函数表达式的指针中解析函数重载和模板实例化,c++,templates,C++,Templates,我有一个通过代码生成的代理对象提供远程过程调用的系统proxy: 它可以获取代理对象和我想要调用的成员的名称,并执行正确的操作 如果我按如下定义remote\u call,只要Foo::bar不是重载或模板,或者参数类型与重载集中的一个成员完全匹配,一切都正常: template <typename T, typename ...Args> void remote_call(Proxy<T> p, void (T::*method)(Args...), Args ...

我有一个通过代码生成的代理对象提供远程过程调用的系统
proxy

它可以获取代理对象和我想要调用的成员的名称,并执行正确的操作

如果我按如下定义
remote\u call
,只要
Foo::bar
不是重载或模板,或者参数类型与重载集中的一个成员完全匹配,一切都正常:

template <typename T, typename ...Args>
void remote_call(Proxy<T> p, void (T::*method)(Args...), Args ... args);
然后一个电话

remote_call(p, &Baz::qux, "string literal");
编译失败,因为
&Baz::qux
未解析为实际应用于以下表达式中的重载

Baz b;
// Converts "string literal" to std::string, calls Baz::qux(std::string)
b.qux("string literal");
下面是我现在所做的,将成员函数的复杂性简化为简单的函数重载情况:

#include <type_traits>

using std::enable_if_t;
using std::is_convertible_v;

template <
          typename Params,
          typename Args,
          typename Method = void (*)(Params),
          typename = enable_if_t<is_convertible_v<Args, Params>>
         >
void remote_call(Method method, Args args)
{
  using R = decltype((*method)(args));

};

#include <string>

void bar(int);
void bar(std::string);

void test()
{
  remote_call(&bar, "string literal");
}
#包括
使用std::enable_if_t;
使用std::is_convertible_v;
模板<
typename参数,
typename参数,
typename方法=void(*)(参数),
typename=如果启用,则启用
>
无效远程调用(方法,Args Args)
{
使用R=decltype((*method)(args));
};
#包括
空白条(int);
空条(标准::字符串);
无效测试()
{
远程_调用(&bar,“字符串文字”);
}

如果有人有一种技术可以使这种方法适用于单参数的情况,我应该能够从中进行归纳。我希望避免将重载解析、模板实例化、参数转换和前面结果的显式规范的负担强加给调用方。编译器知道如果调用表达式
f.bar(“字符串文字”)
出现在源代码中,它会做什么。我想找到一种方法,使它能够在不立即生成代码进行调用的情况下应用这些知识。

Ok的可能重复,链接的问题回答了假定调用方如何解决编译器无法推断出解决方案的歧义。我正试图找到一些方法来展示这种编译器可以推断的API,而无需调用方进行规范。如果将
方法应用于
args
,编译器很容易知道它将调用什么重载/实例化
方法。我正在寻找一种方法来说服它抽象应用与名称解析和参数类型转换完全相同的过程,并给我生成的指向成员函数的指针。见鬼,如果有人能回答非成员的情况,并从重载集或模板实例化中获取函数指针,那就可以了。它是一个类成员的事实在这里并不突出。我将进行编辑以反映成员函数位在这里是一个分散注意力的因素-同样的问题也会出现在非成员身上,需要理解语法负担要清楚,我完全同意将
远程调用
实际实现为一个宏,或者以其他方式使用
decltype(args)
来解决正确的重载。我只是不想让编写调用代码的人不得不写出来。
remote_call(p, &Baz::qux, "string literal");
Baz b;
// Converts "string literal" to std::string, calls Baz::qux(std::string)
b.qux("string literal");
#include <type_traits>

using std::enable_if_t;
using std::is_convertible_v;

template <
          typename Params,
          typename Args,
          typename Method = void (*)(Params),
          typename = enable_if_t<is_convertible_v<Args, Params>>
         >
void remote_call(Method method, Args args)
{
  using R = decltype((*method)(args));

};

#include <string>

void bar(int);
void bar(std::string);

void test()
{
  remote_call(&bar, "string literal");
}