C++ 传递对可变模板的引用
我正在开发一个事件库,我面临可变模板的问题 除了我不能将引用作为参数传递之外,所有这些都工作得很好 下面是一个非常简单的例子,用来说明我的问题C++ 传递对可变模板的引用,c++,templates,c++11,variadic,C++,Templates,C++11,Variadic,我正在开发一个事件库,我面临可变模板的问题 除了我不能将引用作为参数传递之外,所有这些都工作得很好 下面是一个非常简单的例子,用来说明我的问题 struct DelayedSignal { ~DelayedSignal () { std::cout << "~DelayedSignal CLOSE" << std::endl; } template<class C, class... Args> DelayedSign
struct DelayedSignal
{
~DelayedSignal ()
{ std::cout << "~DelayedSignal CLOSE" << std::endl; }
template<class C, class... Args>
DelayedSignal ( void(C::*func)(Args...), C& obj )
{ std::cout << "DelayedSignal INIT - 03 - pointer to method & pointer to class instance (Arg num: " << sizeof...(Args) << ")" << std::endl; }
template<class C, class... Args>
DelayedSignal ( void(C::*func)(Args...), C& obj, Args... args )
{
std::cout << "DelayedSignal INIT - 04 - pointer to method & pointer to class instance & arguments (Arg num: " << sizeof...(Args) << ")" << std::endl;
}
};
template<class... ArgsBis>
struct DelayedSignal_DebugHelper
{
~DelayedSignal_DebugHelper ()
{ std::cout << "~DelayedSignal_DebugHelper CLOSE" << std::endl; }
template<class C, class... Args>
DelayedSignal_DebugHelper ( void(C::*func)(Args...), C& obj )
{ std::cout << "DelayedSignal_DebugHelper INIT - 03 - pointer to method & pointer to class instance (Arg num: " << sizeof...(Args) << ")" << std::endl; }
template<class C, class... Args>
DelayedSignal_DebugHelper ( void(C::*func)(Args...), C& obj, ArgsBis... args ) // Need to use ArgsBis instead of Args to make it work
{
std::cout << "DelayedSignal_DebugHelper INIT - 04 - pointer to method & pointer to class instance & arguments (Arg num: " << sizeof...(Args) << ")" << std::endl;
}
};
template < class Tr, class... Args >
struct Signal
{
void fire ( Args... args ) { std::cout << "Signal::fire::" << sizeof...(Args) << std::endl; }
};
struct Klass {};
int main()
{
std::string str1("Blop"); // Will be used as reference
Klass k; // Will be used as reference
Signal<void, Klass&> signal_01;
Signal<void, std::string&> signal_02;
std::cout << "====== DelayedSignal :: needed for production purpose ===============" << std::endl;
// OK
DelayedSignal test01(&Signal<void, std::string&>::fire, signal_02);
// HERE IS THE PROBLEM
//DelayedSignal test02(&Signal<void, std::string&>::fire, signal_02, str1);
// OK
DelayedSignal test03(&Signal<void, Klass&>::fire, signal_01);
// HERE IS THE PROBLEM
//DelayedSignal test04(&Signal<void, Klass&>::fire, signal_01, k);
std::cout << "====== DelayedSignal_DebugHelper :: used only for debug purpose ======" << std::endl;
// OK
DelayedSignal_DebugHelper<std::string&> test05(&Signal<void, std::string&>::fire, signal_02);
// OK
DelayedSignal_DebugHelper<std::string&> test06(&Signal<void, std::string&>::fire, signal_02, str1);
// OK
DelayedSignal_DebugHelper<Klass&> test07(&Signal<void, Klass&>::fire, signal_01);
// OK
DelayedSignal_DebugHelper<Klass&> test08(&Signal<void, Klass&>::fire, signal_01, k);
return 1;
}
struct DelayedSignal
{
~DelayedSignal()
{std::cout我使用的是clang,它给出了一个绝对难以置信的错误消息:
test.cpp:59:19: error: no matching constructor for initialization of 'DelayedSignal'
DelayedSignal test02(&Signal<void, std::string&>::fire, signal_02, str1);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test.cpp:9:5: note: candidate constructor template not viable: requires 2 arguments, but 3 were provided
DelayedSignal ( void(C::*func)(Args...), C& obj )
^
test.cpp:13:5: note: candidate template ignored: deduced conflicting types for parameter 'Args'
(<std::__1::basic_string<char> &> vs. <std::__1::basic_string<char>>)
DelayedSignal ( void(C::*func)(Args...), C& obj, Args... args )
^
test.cpp:59:19:错误:没有用于“DelayedSignal”初始化的匹配构造函数
延迟信号测试02(和信号::火灾、信号_02、str1);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test.cpp:9:5:注意:候选构造函数模板不可行:需要2个参数,但提供了3个
延迟信号(无效(C::*func)(参数…,C&obj)
^
test.cpp:13:5:注意:已忽略候选模板:推断参数“Args”的冲突类型
(对)
DelayedSignal(无效(C::*func)(参数…,C&obj,参数…)
^
编译器为Args
推断冲突类型:
std::string&
std::string
我相信解决这一问题的最佳方法就是如何使用您的DelayedSignal\u DebugHelper
Howard Hinnant是正确的……另一种可能是在任何地方使用引用,例如:
#include <iostream>
struct DelayedSignal
{
~DelayedSignal ()
{ std::cout << "~DelayedSignal CLOSE" << std::endl; }
template<class C, class... Args>
DelayedSignal ( void(C::*func)(Args &...), C& obj )
{ std::cout << "DelayedSignal INIT - 03 - pointer to method & pointer to class instance (Arg num: " << sizeof...(Args) << ")" << std::endl; }
template<class C, class... Args>
DelayedSignal ( void(C::*func)(Args &...), C& obj, Args & ... args )
{
std::cout << "DelayedSignal INIT - 04 - pointer to method & pointer to class instance & arguments (Arg num: " << sizeof...(Args) << ")" << std::endl;
}
};
template < class Tr, class... Args >
struct Signal
{
void fire ( Args &... args ) { std::cout << "Signal::fire::" << sizeof...(Args) << std::endl; }
};
struct Klass {};
int main()
{
std::string str1("Blop"); // Will be used as reference
Klass k; // Will be used as reference
Signal<void, Klass&> signal_01;
Signal<void, std::string&> signal_02;
std::cout << "====== DelayedSignal :: needed for production purpose ===============" << std::endl;
// OK
DelayedSignal test01(&Signal<void, std::string&>::fire, signal_02);
// HERE IS THE PROBLEM
DelayedSignal test02(&Signal<void, std::string&>::fire, signal_02, str1);
}
#包括
结构延迟信号
{
~DelayedSignal()
{std::cout既然你已经接受了答案,这只是一个补充。
虽然我可能会忽略一些东西,identity
类模板
以下内容似乎使您的代码可编译。
例如:
template<class T> struct identity { typedef T type; };
struct DelayedSignal
{
...
template<class C, class... Args>
DelayedSignal ( void(C::*func)(Args...), C& obj, typename identity<Args>::type... args )
{
...
}
};
模板结构标识{typedef T type;};
结构延迟信号
{
...
模板
DelayedSignal(void(C::*func)(Args…),C&obj,typename identity@Valke你不应该用C++0x标记这个吗?我试着编译你的解决方案,想知道为什么它在Visual Studio 2011中不起作用;在查找可变模板后,我才意识到如果搜索正确,这是一个新功能。到底是什么编译器支持这个功能?@leet:添加了标记。这个功能是h从4.3版开始,g++就一直支持这一点——有关更多信息,请参阅此链接:@Ben Voigt:我正在使用GCC 4.5。0@leetNightshade:哦,对不起,是的,我确实使用C++0x编译它。@TonyK:谢谢您添加了标记。您好,非常有趣,而且…很奇怪。我的错误消息没有那么描述性:main.cpp:2:74:错误:没有用于调用的匹配函数'DelayedSignal::DelayedSignal(void(Signal::*)(std::basic_string&),Signal&,std::string&)main.cpp:57:1:注:候选项为:DelayedSignal::DelayedSignal(const DelayedSignal&)
但您对冲突类型的看法似乎是正确的。我没有太过强硬……我想我必须改变我实现延迟信号的方式。感谢您的帮助。此解决方案至少部分解决了我的问题。这两个答案都是有效的,但由于我只能选择其中一个,因此我选择了具有部分解决方案的一个N