У меня есть класс, который должен поддерживать динамический набор аргументов типа, но VS2012 не поддерживает вариационные шаблоны. (VS2013 и компилятор CTP сделать поддержку VARIADIC шаблоны, но я не могу их использовать. Не могу я использовать Boost.)Visual Studio 2012: нет вариационных шаблонов: решение?
Итак, я пытаюсь найти решение, используя «шаблоны специализации». Ниже я до сих пор. (Обратите внимание, что если вы переименуете 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: неразрешенный внешний символ «общественности: статический класс сигнализатора ShadingSystem :: Signal_ShaderUpdated»(Signal_ShaderUpdated @ ShadingSystem @ 2V $ сигнализатора @ PEAVShader @@@ spectralCore @@?) D: \ spectralGraph.lib (VNScene.obj)
То, что Microsoft использовала для имитации вариационных шаблонов в STL, заключалось в том, чтобы включать один и тот же заголовок несколько раз с некоторыми макросами, определенными по-разному, чтобы он расширялся в шаблоны с различным количеством аргументов. Это уродливо, но вы можете использовать тот же трюк. – Trillian
Спасибо. Конечно, это способ сделать. Но сначала я должен уметь определять это вручную ... это то, что я пытаюсь сделать прямо сейчас! Как только у меня будет этот компилятор кода ... Я смогу работать над макросом ;-) – Spectral
Я не думаю, что строка '(* i) .template target() == f .template target () 'делает то, что вы думаете. Вы не можете проверить 'std :: function' за равенство в том, как вы его используете - вам нужны отдельные маркеры. –
Xeo