Функциональная подпись как параметр шаблона

Можно ли добиться чего-то подобного:

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 использует для эмуляции вариативных шаблонов в стандартной библиотеке).