Can a function type without a pointer be a non-peak parameter?

I experimented with function types in C ++. Note that I do not mean the types of pointers to a function like:

typedef void (*voidFuncPtr)(); 

but all the more exotic:

 typedef void (voidFunc)(); 

I did not expect the following code to compile, but surprisingly this happened:

 template<voidFunc func> class funcClass { public: void call() { func(); }; }; void func() { } void Test() { funcClass<func> foobar; foobar.call(); } 

however, if I try to add the following to funcClass:

 voidFuncPtr get() { return &func; } 

I get an error message Address expression must be an lvalue or a function designator

My first question here is: what kind of black magic is used by the compiler to pretend that the type func is what it really can pass around the instance? Is it just treating it like a link? The second question: if it can even be called, why cannot it be addressed to him? Also, what are these non-pointer types called? I just opened them because of boost :: function and could never find documentation about them.

+4
source share
2 answers

Β§14.1.4 of the Standard states:

A non-type template parameter must have one of the following (optional cv-qualified) types:

- integral or enumerated type,

- a pointer to an object or a pointer to a function , [this is what you have]

- lvalue reference to an object reference or lvalue to a function,

- a pointer to a member,

- std :: nullptr_t.

And in Β§14.1.6 it says

The non-type template parameter with no reference is the value of prvalue. It should not be tied or in any other way change its meaning. A non-type parameter of a template without a link cannot accept its address . When a non-type non-reference template parameter is used as an initializer, the temporary is always used for the reference.

So this explains the two behaviors that you see.

Note that func same as &func (Β§14.3.2.1):

[A parameter of a template without a type can be] a constant expression (5.19), which denotes the address of an object with a static storage duration and external or internal communication, or a function with external or internal communication, including function templates and function templates, but excluding non-static class members, expressions (ignoring parentheses) as well as an id expression, except that it can be omitted if the name refers to a function or array and should be omitted if the corresponding parameter template is Help; or...

So this is just a pointer to a function.

+4
source

Given that compiling code without a pointer and pointers (including functions and member functions) are valid template arguments, it seems that the compiler considers voidFunc be a type of function pointer, i.e. decomposed version of the type. The rules for this have not changed between C ++ 2003 and C ++ 2011.

+2
source

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


All Articles