简体   繁体   English

指向成员函数的指针的模板类型推导

[英]Template type deduction for a pointer to member function

I have a very similar problem to that presented by Morpheus, in the following question: 我有一个与Morpheus提出的问题非常相似的问题,在下面的问题中:

Overloaded member function pointer to template 重载的成员函数指向模板的指针

The solution proposed by Richard Corden requires the user to explicitly specify the function parameter type, to distinguish it among the overloads. Richard Corden提出的解决方案要求用户明确指定函数参数类型,以区分它们的重载。 However, this solution does not seem to work with overloads with a varying number of arguments of the same type . 但是,此解决方案似乎不适用于具有相同类型的不同数量的参数的重载。

Consider this example (derived from the original question): 考虑这个例子(源自原始问题):

template <typename T>
class A
{
public:
  template<class Arg1>
  void connect(void (T::*f)(Arg1)) 
  {
    //Do some stuff
  }

  template<class Arg1, class Arg2>
  void connect(void (T::*f)(Arg1,Arg2)) 
  {
    //Do some stuff
  }

  void connect(void (T::*f)()) 
  {
    //Do some stuff
  }
};

class GApp
{
public:
    void foo() {}
    void foo(double d) {}
    void foo(double d1, double d2) {}
};


int main ()
{
  A<GApp> a;
  a.connect (&GApp::foo);                // foo () - OK
  a.connect<double> (&GApp::foo);        // foo (double) - FAIL
  a.connect<double,double> (&GApp::foo); // foo (double,double) - OK
}

GNU G++ 3.4.5 and MSVC 2008 do not compile the code above, both presenting similar error messages: GNU G ++ 3.4.5和MSVC 2008不编译上面的代码,两者都提供类似的错误消息:

test.cpp: In function `int main()':
test.cpp:36: error: call of overloaded `connect(<unknown type>)' is ambiguous
test.cpp:7: note: candidates are: void A<T>::connect(void (T::*)(Arg1)) [with Arg1 = double, T = GApp]
test3.cpp:13: note:               void A<T>::connect(void (T::*)(Arg1, Arg2)) [with Arg1 = double, Arg2 = double, T = GApp]

I'm aware of some workarounds that can make it compile, like assigning the pointer to a variable of the exact same type (eg void (GApp::*tmp)(double) = &GApp::foo; ) or, using a more explicity form when calling the connect function (eg connect((void (GApp::*)(double))(&GApp::foo)); ). 我知道一些可以使其编译的变通方法,比如将指针指定给完全相同类型的变量(例如void (GApp::*tmp)(double) = &GApp::foo; )或者,使用更多调用connect函数时的表达形式(例如connect((void (GApp::*)(double))(&GApp::foo)); )。

However, I prefer the first solution and would like to know why it is not working. 但是,我更喜欢第一种解决方案,并想知道它为什么不起作用。

Thank you in advance! 先感谢您!

For a.connect<double> (&GApp::foo) , both the foo(double) and foo(double, double) will match the overload of connect with one, and with two template parameters respectively (in the case of the two parameter version, the second template argument will be deduced, the first argument was provided by you explicitly). 对于a.connect<double> (&GApp::foo)foo(double)foo(double, double)将匹配connect的重载与one,并分别与两个模板参数匹配(在两个参数的情况下)版本,将推导出第二个模板参数,第一个参数由您明确提供)。

If you want to disambiguate ambiguous cases, I recommend that you pass the exact type, so no surprises can happen. 如果你想消除模棱两可的情况,我建议你传递确切的类型,这样就不会出现任何意外。 Instead of those overloads, why not have a single overload 而不是那些重载,为什么不有一个重载

template<typename MType, typename T>
void connect(MType T::*f) 
{
  //Do some stuff
}

a.connect<void()> (&GApp::foo);
a.connect<void(double)> (&GApp::foo);
a.connect<void(double, double)> (&GApp::foo);

The last call to connect should work fine in your code too. 最后一次调用connect应该在你的代码中正常工作。 You then can dissect the type MType in connect with separate templates, to get the parameter and return types. 然后,您可以在connect单独模板时剖析类型MType ,以获取参数和返回类型。

The problem with the original code is that you are explicitly defining the wrong part. 原始代码的问题在于您明确定义了错误的部分。 When you specify a list of template parameters, even when you specify one, the compiler will attempt to deduce the second one and then it runs right back into ambiguity because it doesn't know if you want to use (double,double) or (double) variation. 当你指定一个模板参数列表时,即使你指定了一个模板参数列表,编译器也会尝试推导出第二个模板参数,然后它会立即运行到模糊状态,因为它不知道你是否想要使用(double,double)或(双)变异。

Instead of defining template parameters, let the compiler deduce them but explicitly specify which one of the foo() functions you want to use: 让编译器推导出它们,而不是定义模板参数,而是明确指定要使用哪个foo()函数:

int main()
{
    A<GApp> a;
    a.connect (&GApp::foo);                                     // foo () - OK
    a.connect( ( void (GApp::*)(double) )&GApp::foo);           // foo (double) - OK
    a.connect( ( void (GApp::*)(double, double) ) &GApp::foo);  // foo (double,double) - OK
}

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

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