Function signature-like expressions as C++ template arguments

With regards to your first question - about the type int(char, float) - this is a valid C++ type and is the type of a function that takes in a char and a float and returns an int. Note that this is the type of the actual function, not a function pointer, which would be an int (*) (char, float). The actual type of any function is this unusual type. For example, the type of

void DoSomething() {
    /* ... */
}

is void ().

The reason that this doesn't come up much during routine programming is that in most circumstances you can't declare variables of this type. For example, this code is illegal:

void MyFunction() { 
    void function() = DoSomething; // Error!
}

However, one case where you do actually see function types used is for passing function pointers around:

void MyFunction(void FunctionArgument()) {
     /* ... */
}

It's more common to see this sort of function written to take in a function pointer, but it's perfectly fine to take in the function itself. It gets casted behind-the-scenes.

As for your second question, why it's illegal to have the same template written with different numbers of arguments, I don't know the exactly wording in the spec that prohibits it, but it has something to do with the fact that once you've declared a class template, you can't change the number of arguments to it. However, you can provide a partial specialization over that template that has a different number of arguments, provided of course that the partial specialization only specializes over the original number of arguments. For example:

template <typename T> class Function;
template <typename Arg, typename Ret> class Function<Ret (Arg)> { 
    /* ... */
};

Here, Function always takes one parameter. The template specialization takes in two arguments, but the specialization is still only over one type (specifically, Ret (Arg)).


int* int_pointer;    // int_pointer   has type "int*"
int& int_reference;  // int_reference has type "int&"
int  int_value;      // int_value     has type "int"

void (*function_pointer)(int, int);    // function_pointer has type
                                       // "void (*)(int, int)"
void (&function_reference)(int, int);  // function_reference has type
                                       // "void (&)(int ,int)"
void function(int, int);               // function has type
                                       // "void(int, int)"

template<>
struct Object1<void(int, int)>
{
    void m_member1(int, int);  // wait, what?? not a value you can initialize.
};