Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function signature as template parameter

Is it possible to achieve something like this:

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)

Return type is always void.

I want to send as template parameter the function signature. Is this possible? I can't use variadic templates as my compiler doesn't support this feature yet.

like image 996
Mircea Ispas Avatar asked Jan 21 '13 15:01

Mircea Ispas


People also ask

How do you name a template parameter?

If there is just a single template parameter, I name it T (or U,V for nested templates). When there are multiple parameters and the use is not immediately obvious then I use descriptive names prefixed with T. For example, TKey, TValue, TIdentifiier, etc ...

Can a template be a template parameter?

A template argument for a template template parameter is the name of a class template. When the compiler tries to find a template to match the template template argument, it only considers primary class templates. (A primary template is the template that is being specialized.)

How do you call a function in a template?

A function template starts with the keyword template followed by template parameter(s) inside <> which is followed by the function definition. In the above code, T is a template argument that accepts different data types ( int , float , etc.), and typename is a keyword.

Is function name part of signature?

A function's signature includes the function's name and the number, order and type of its formal parameters. Two overloaded functions must not have the same signature. The return value is not part of a function's signature.


2 Answers

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 */ }

Continue the tedious repetition until you have enough arguments for your needs. In TR1 it was recommended that the various function object templates be able to handle 10 arguments. This was typically implemented with fairly sophisticated macros to simplify coding, but it can be done by brute force.

like image 127
Pete Becker Avatar answered Sep 19 '22 16:09

Pete Becker


With variadic templates you would make one partial specialization to break down the signature into its parts:

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;
};

Without variadic templates you have to make one specialization for each number of arguments. Macros may be of help to generate all those (Boost.PP, or maybe those that Visual Studio uses to emulate variadic templates in the standard library).

like image 29
R. Martinho Fernandes Avatar answered Sep 20 '22 16:09

R. Martinho Fernandes