Function with default parameter as template type

I am trying to use a function with a default argument as a parameter to a function pointer template:

template <void (*F)()> class A {}; void foo1(int a = 0) {} void foo2() {} int main() { //A<foo1> a1; <-- doesn't work A<foo2> a2; } 

Compiler Error:

main.cpp: 7: 7: error: cannot convert template argument 'foo1 to' void (*) ()

Is there a specific syntax for this? Or a specific language restriction? Otherwise, the alternative is to have two separate functions instead of the default parameter:

 void foo1(int a) {} void foo1() { foo1(0); } 

Update I understand that the signatures are different, but I wonder if there is a way to make this work convenient without requiring changing all the functions with default parameters?

+4
source share
5 answers

In accordance with section 8.3.6 of the C ++ standard

If an expression is specified in a parameter declaration, that expression is used as the default argument. The default arguments will be used in calls where missing arguments are missing.

Since A<foo1> not a function call, the arguments are ignored by default. In fact, they are ignored in all contexts except function calls, for example

 typedef void (*FFF)(); FFF x = foo1; 

will not compile and create the same message that you get when you try to use foo1 as a template parameter:

 error: invalid conversion from 'void (*)(int)' to 'void (*)()' 

This makes sense because evaluating the default arguments is a separate step in the call:

8.3.6.9: the default arguments will be evaluated each time the function is called.

Having arguments by default does not change the signature of your function. For example, you cannot use a function with a single argument with a default argument to override a virtual member function without arguments.

+2
source

The signature of foo1 is void(int) , not void() . That is why it does not convert to void(*)() .

You confuse the default arguments when overloading.

+3
source

The default argument values ​​are not part of the function type. You cannot use foo1 as a function without arguments, because it takes one argument. The argument is populated for you if you don't mention it, but it is still there.

Your workaround, including the dispatch feature, seems like a good solution. It can even be templated if you need it.

+2
source

I am sure that the function pointer has a function signature with all the default parameters, and function pointers cannot convert to a function pointer with a different signature. Finding this out in the standard is another matter though ...

I think the corresponding proposal from the standard is 8.3.5 [dcl.fct] clause 6:

... The return type, a list of parameter parameters, ref-qualifier and cv-qualifier-seq, but not the default arguments (8.3.6) or the exception specification (15.4), are part of the function type. [Note. Function types are checked when assigning and initializing function pointers, function references, and member function pointers. -end note]

Note that the default arguments are children of the form = value in accordance with 8.3.6 [dcl.fct.default], clause 1:

If an initializer clause is specified in a parameter declaration, this initializer condition is used as the default argument ....

+2
source

It will not compile because foo1 has a signature:

 void foo1(int a); 

which you are trying to insert in a pointer to:

 void F() 

Function signatures do not match. The fact that foo1 has a default parameter does not change the signature of the function (it can still be int ).

More general solution

I would say forget about templates, they limit you here.

Personally, I solve the callback problem using function objects with argument binding. This can be done using the boost :: function library and binding default arguments using boost :: bind (or std::bind1st and std::bind2nd ).

These accelerator libraries are also built into the new C ++ 11 standard, like std::function , and std::bind .

It's worth taking a look at this, as it allows you to do very nice things, for example, provide default arguments for functions or use member functions of a class as callbacks.

There are many code examples on the sites I linked to everyone, and boost links have tutorials.

+1
source

Source: https://habr.com/ru/post/1446568/


All Articles