我正在尝试通过以下模板存储成员函数指针:(这是我的真实代码的简化版本)
template<class Arg1>
void connect(void (T::*f)(Arg1))
{
//Do some stuff
}
template<class Arg1>
void connect(void (T::*f)())
{
//Do some stuff
}
class GApp
{
public:
void foo() {}
void foo(double d) {}
};
然后我想对GApp中的每个重载方法执行以下操作:
connect(&GApp::foo);
为foo()
调用此功能是可以的,但如何为foo(double d)
调用此功能?以下为什么不工作?
connect((&GApp::foo)(double));
它会给我
语法错误:'double'应以')'
开头
我不明白这里必须使用的语法。这可能是一个愚蠢的问题,但任何人都可以帮助我吗?
答案 0 :(得分:6)
您编写的代码无法编译。我对你想做的事做了一些“假设”,并改变了代码。
总而言之,您可以通过显式指定函数参数类型来调用正确的函数:
connect<double> (&GApp::foo);
如果connect方法是类模板的成员,那么只需要指定一次类类型:
template <typename T> class A
{
public:
template<class Arg1>
void connect(void (T::*f)(Arg1))
{
//Do some stuff
}
void connect(void (T::*f)())
{
//Do some stuff
}
};
class GApp
{
public:
void foo() {}
void foo(double d) {}
};
int main ()
{
A<GApp> a;
a.connect (&GApp::foo); // foo ()
a.connect<double> (&GApp::foo); // foo (double)
}
<强>更新强>
响应新代码示例,所有信息都被传入。“罕见”情况是'signal_void'情况,因为这是信号具有模板参数,但成员函数没有。因此我们特例就是这个例子,然后我们就完成了。以下现在编译:
template <class Arg = void>
class signal {};
signal<double> signal_double;
signal<> signal_void;
// Arg1 is deduced from signal<Arg1> and then we use it in the declaration
// of the pointer to member function
template<class T, class Arg1>
void connect ( signal<Arg1>& sig, T& obj, void (T::*f)(Arg1) ) {}
// Add special case for 'void' without any arguments
template<class T>
void connect (signal<> & sig, T& obj, void (T::*f)()) {}
void bar ()
{
GApp myGApp;
//Connecting foo()
connect(signal_void, myGApp, &GApp::foo); // Matches second overload
//Connecting foo(double)
connect(signal_double, myGApp, &GApp::foo); // Matches first overload
}
答案 1 :(得分:5)
C ++编程语言,3E,第7.7节,第159页:
您可以通过分配或初始化函数指针来获取重载函数的地址。在这种情况下,目标的类型用于从重载函数集中进行选择。例如:
void f(int);
int f(char);
void (*pf1)(int) = &f; // void f(int);
int (*pf2)(char) = &f; // int f(char);
void (*pf3)(char) = &f; // error: no void f(char)
据我所知(尚未检查),同样适用于会员功能。所以解决方案可能分为两行:
connect((&GApp::foo)(double));
变为:
void (GApp::*tmp)(double) = &GApp::foo;
connect(tmp);
永远不要调用变量tmp
; - )
我猜想newacct的演员也是安全的,原因完全相同。转换为void (GApp::*)(double)
定义为与初始化void (GApp::*)(double)
类型的临时值相同。由于用于初始化它的表达式是&GApp::foo
,我希望同样的魔术应用于强制转换,适用于任何其他具有重载函数的初始化。 Stroustrup没有说“初始化一个指向函数的指针变量”,他说“初始化一个指向函数的指针”。所以这应该包括临时工。
所以如果你喜欢单行:
connect((void (GApp::*)(double))(&GApp::foo));
但是,我假设标准与我一致的想法一致,我没有检查过。
答案 2 :(得分:1)
您可以尝试显式地转换指针,让它知道选择哪一个,如下所示:
connect((void (GApp::*)(double))&GApp::foo);
免责声明:尚未测试
答案 3 :(得分:0)
这很有效,
typedef void (GApp::*MemberFunctionType)(double);
MemberFunctionType pointer = &GApp::foo;
connect(MemberFunctionType);
为什么?
修改
嗯..是的。它与newacct的解决方案相同。任何人都可以提供解决方案吗?答案 4 :(得分:0)
使用boost :: function library ...
#include <boost/function.hpp>
template<class Arg1>
void connect(boost::function1<void, Arg1*> fn)
{
//Do some stuff
}
template<class Arg1>
void connect(boost::function2<void, Arg1*, double> fn)
{
//Do some stuff
}
class GApp
{
public:
void foo() {}
void foo(double d) {}
};
int main()
{
boost::function1<void,GApp*> f1 = (void (GApp::*)(void)) &GApp::foo;
boost::function2<void,GApp*,double> f2 = (void (GApp::*)(double)) &GApp:foo;
connect(f1);
connect(f2);
return 0;
}
答案 5 :(得分:0)
我的原始代码是这样的,
...连接器
template<class T, class Arg1>
void connect(signal<Arg1>& sig,T& obj, void (T::*f)())
{
// sig.insert(new GFunction<T, Arg1>(&obj,f));
}
template<class T, class Arg1
void connect(signal<Arg1>& sig,T& obj, void (T::*f)(Arg1))
{
// sig.insert(new GFunction<T, Arg1>(&obj,f));
}
信号...
signal<double> signal_double;
signal<> signal_void;
应用程序...
class GApp
{
public:
void foo() {}
void foo(double d) {}
};
最后,连接......
//Connecting foo()
connect(signal_void, myGApp, &GApp::foo()); //Ok
//Connecting foo(double)
connect(signal_double, myGApp, &GApp::foo()); // but ERROR!
有信号的模板类(这里没有提到)。我希望现在情况更清楚了。 (或者它与previouse相同吗?)。如果没有foo()(只有foo(double)),第二个连接将工作。这就是我的代码伤害了我的事情。 :(