【发布时间】:2013-12-14 14:18:59
【问题描述】:
我有一个类需要支持一组动态类型参数,但是 VS2012 不支持可变参数模板。 (VS2013 和编译器 CTP 做 支持可变参数模板,但我不能使用它们。我也不能使用 Boost。)
所以,我正在尝试通过使用“模板专业化”来找到解决方案。以下是我到目前为止所拥有的。 (请注意,如果您将 Signaler2 重命名为 Signaler...,则会出现一些编译问题。)
关于如何解决这个问题的任何想法?
#include <functional>
#include <vector>
using namespace std;
namespace spectralCore
{
#pragma region Signaler2<T1, T2>
// A signal object to handle signal/events notifications.
template<typename T1, typename T2>
class Signaler2
{
public:
typedef std::function<void (T1,T2)> Func;
public:
void Call(T1 arg1, T2 arg2)
{
for(auto i = _handlers.begin(); i != _handlers.end(); i++)
(*i)(arg1, arg2);
for(auto i = _postHandlers.begin(); i != _postHandlers.end(); i++)
(*i)(arg1, arg2);
}
void operator ()(T1 arg1, T2 arg2)
{
Call(arg1, arg2);
}
Signaler2& operator*=(Func f)
{
_postHandlers.push_back( f );
return *this;
}
Signaler2& operator/=(Func f)
{
for(auto i = _postHandlers.begin(); i != _postHandlers.end(); i++)
{
if ( (*i).template target<void (T1,T2)>() == f.template target<void (T1,T2)>() )
{
_postHandlers.erase( i );
break;
}
}
return *this;
}
Signaler2& operator+=(Func f)
{
_handlers.push_back( f );
return *this;
}
Signaler2& operator-=(Func f)
{
for(auto i = _handlers.begin(); i != _handlers.end(); i++)
{
if ( (*i).template target<void (T1,T2)>() == f.template target<void (T1,T2)>() )
{
_handlers.erase( i );
break;
}
}
return *this;
}
bool IsRegistered(Func f)
{
for(auto i = _handlers.begin(); i != _handlers.end(); i++)
if ( (*i).template <void (T1,T2)>() == f.template target<void (T1,T2)>() )
true;
return false;
}
private:
std::vector<Func> _handlers;
std::vector<Func> _postHandlers;
};
#pragma endregion
#pragma region Signaler<T1>
// A signal object to handle signal/events notifications.
//template<typename T1> class Signaler<T1,void>
template<typename T1>
class Signaler
{
public:
typedef std::function<void (T1)> Func;
public:
void Call(T1 arg)
{
for(auto i = _handlers.begin(); i != _handlers.end(); i++)
(*i)( arg );
for(auto i = _postHandlers.begin(); i != _postHandlers.end(); i++)
(*i)( arg );
}
void operator ()(T1 arg)
{
Call( arg );
}
Signaler& operator+=(Func f)
{
_handlers.push_back( f );
return *this;
}
Signaler& operator-=(Func f)
{
for(auto i = _handlers.begin(); i != _handlers.end(); i++)
{
if ( (*i).template target<void (T1)>() == f.template target<void (T1)>() )
{
_handlers.erase( i );
break;
}
}
return *this;
}
Signaler& operator*=(Func f)
{
_postHandlers.push_back( f );
return *this;
}
Signaler& operator/=(Func f)
{
for(auto i = _postHandlers.begin(); i != _postHandlers.end(); i++)
{
if ( (*i).template target<void (T1)>() == f.template target<void (T1)>() )
{
_postHandlers.erase( i );
break;
}
}
return *this;
}
bool IsRegistered(Func f)
{
for(auto i = _handlers.begin(); i != _handlers.end(); i++)
if ( (*i).template target<void (T1)>() == f.template target<void (T1)>() )
true;
return false;
}
private:
std::vector<Func> _handlers; // First step handlers
std::vector<Func> _postHandlers; // Second step handlers
};
#pragma endregion
#pragma region Signaler<void>
// A signal object to handle signal/events notifications.
template<>
class Signaler<void>
{
public:
typedef std::function<void (void)> Func;
public:
void Call()
{
for(auto i = _handlers.begin(); i != _handlers.end(); i++)
(*i)();
for(auto i = _postHandlers.begin(); i != _postHandlers.end(); i++)
(*i)();
}
void operator ()()
{
Call();
}
Signaler& operator*=(Func f)
{
_postHandlers.push_back( f );
return *this;
}
Signaler& operator/=(Func f)
{
for(auto i = _postHandlers.begin(); i != _postHandlers.end(); i++)
{
if ( (*i).template target<void (void)>() == f.template target<void (void)>() )
{
_postHandlers.erase( i );
break;
}
}
return *this;
}
Signaler& operator+=(Func f)
{
_handlers.push_back( f );
return *this;
}
Signaler& operator-=(Func f)
{
for(auto i = _handlers.begin(); i != _handlers.end(); i++)
{
if ( (*i).template target<void (void)>() == f.template target<void (void)>() )
{
_handlers.erase( i );
break;
}
}
return *this;
}
bool IsRegistered(Func f)
{
for(auto i = _handlers.begin(); i != _handlers.end(); i++)
if ( (*i).template target<void (void)>() == f.template target<void (void)>() )
true;
return false;
}
private:
std::vector<Func> _handlers; // First step handlers
std::vector<Func> _postHandlers; // Second step handlers
};
#pragma endregion
}
注意到我也尝试了以下定义:
template<typename T1, typename T2=void> class Signaler
{ ... }
template<typename T1> class Signaler<T1,void>
{ ... }
template<> class Signaler<void,void>
{ ... }
但我收到“LINK”错误:
错误 LNK2001:未解析的外部符号“公共:静态类 Signaler ShadingSystem::Signal_ShaderUpdated”(?Signal_ShaderUpdated@ShadingSystem@2V?$Signaler@PEAVShader@@@spectralCore@@A) D:\spectralGraph.lib(VNScene.obj )
【问题讨论】:
-
微软过去在 STL 中模仿可变参数模板的做法是多次包含相同的标头,其中一些宏定义不同,以便扩展为具有不同数量参数的模板。这很丑陋,但您也许可以使用相同的技巧。
-
谢谢。当然这是一种方法。但首先我必须能够手动定义它......这是我现在尝试做的!一旦我编译了这段代码......我将能够处理宏;-)
-
我不认为
(*i).template target<void (T1,T2)>() == f.template target<void (T1,T2)>()行做你认为它做的事。您无法检查std::function的使用方式是否相等 - 您需要单独的令牌。
标签: c++ templates visual-studio-2012 template-specialization variadic