Функциональная подпись как параметр шаблона
Можно ли добиться чего-то подобного:
template<typename Signature>
class Test
{
public:
//here I want operator () to respect the signature
};
Test<void(int)> t1; //void operator()(int)
Test<void(int, float)> t2; //void operator()(int, float)
Тип возврата всегда void
.
Я хочу отправить в качестве параметра шаблона подпись функции. Это возможно?
Я не могу использовать вариативные шаблоны, поскольку мой компилятор еще не поддерживает эту функцию.
Ответы
Ответ 1
template <class Ty>
class Test; /* not defined */
template <class Ret, class Arg0>
class Test<Ret(Arg0)> { /* whatever */ }
template <class Ret, class Arg0, class Arg1>
class Test<Ret(Arg0, Arg1)> { /* whatever */ }
template <class Ret, class Arg0, class Arg1, class Arg2>
class Test<Ret(Arg0, Arg1, Arg2)> { /* whatever */ }
Продолжайте утомительное повторение, пока у вас не будет достаточно аргументов для ваших нужд. В TR1 было рекомендовано, чтобы различные шаблоны функциональных объектов могли обрабатывать 10 аргументов. Обычно это было реализовано с помощью довольно сложных макросов, чтобы упростить кодирование, но это можно сделать с помощью грубой силы.
Ответ 2
С вариационными шаблонами вы должны сделать одну частичную специализацию, чтобы разбить подпись на ее части:
template<typename Signature>
class Test;
// or the SFINAE-friendlier
//template<typename Signature>
//class Test {};
// or the hard-error-friendlier
//template<typename Signature>
//class Test {
// static_assert(Bool<false, Signature>{},
// "template argument must be a signature returning void");
// // Bool is from http://flamingdangerzone.com/cxx11/2012/05/29/type-traits-galore.html#dependent_boolean
//};
template<typename... Args>
class Test<void(Args...)>
{
public:
void operator()(Args...) const;
};
Без вариационных шаблонов вам нужно сделать одну специализацию для каждого количества аргументов. Макросы могут помочь сгенерировать все это (Boost.PP или, возможно, те, которые Visual Studio использует для эмуляции вариативных шаблонов в стандартной библиотеке).