I have a class that needs to support a dynamic set of type arguments, but VS2012 does not support variadic templates. (VS2013 and the compiler CTP do support variadic templates, but I can't use them. Nor can I use Boost.)
So, I'm trying to find a solution by using "templates specialization". Below is what I have so far. (Notice that if you rename Signaler2 by Signaler... there are some compilation issues.)
Any ideas on how to solve this problem?
#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
}
Notices that I have also try the following definition :
template<typename T1, typename T2=void> class Signaler
{ ... }
template<typename T1> class Signaler<T1,void>
{ ... }
template<> class Signaler<void,void>
{ ... }
But I got a "LINK" error :
error LNK2001: unresolved external symbol "public: static class Signaler ShadingSystem::Signal_ShaderUpdated" (?Signal_ShaderUpdated@ShadingSystem@2V?$Signaler@PEAVShader@@@spectralCore@@A) D:\spectralGraph.lib(VNScene.obj)