The output of the template argument for the function pointer (g ++ and ICC vs Clang ++ and VC ++)

Consider the following program:

#include <iostream> template <typename T> void foo(const T* x) { x(); } void bar() { std::cout<<"bar() is called\n"; } int main() { foo(bar); } 

It compiles fine on clang++ and VC++ , but g++ gives the following compiler error (see live demo here )

 main.cpp: In function 'int main()': main.cpp:10:9: error: no matching function for call to 'foo(void (&)())' foo(bar); ^ main.cpp:3:6: note: candidate: template<class T> void foo(const T*) void foo(const T* x) { ^~~ main.cpp:3:6: note: template argument deduction/substitution failed: main.cpp:10:9: note: types 'const T' and 'void()' have incompatible cv-qualifiers foo(bar); ^ 

I used -pedantic-errors when using g++ and clang++ , and I used the /W4 and /Za option when using the VC ++ compiler. See here the demo here and here . So, I want to know how the template type parameter T will be displayed here? If I remove const from the program, then it also compiles to g++ . If I use const T& then it compiles on all 3 compilers. So, how exactly will the type be displayed here in these cases?

Update:

This program also does not work in compilation on the Intel C ++ compiler. See here the demo here . So, is this a bug in g++ and Intel C ++ or a bug in clang++ and VC ++?

+7
c ++ language-lawyer const function-pointers template-deduction
source share
1 answer

This is essentially CWG issue 1584 :

It is unclear whether the following is correctly formed:

 void foo(){} template<class T> void deduce(const T*) { } int main() { deduce(foo); } 

Implementations vary in their interpretation of this example.

He is currently active. It is impossible to say which compiler is right. Although, as noted in the 2015 note, the consensus in the WGE now is that this should be rejected.


To give a little more context, we must remember that the type of a function with cv-qualifier-seq has a special meaning (think member functions) and is not just a type that means something that cannot be changed. Moreover, you cannot even add the cv qualification in any hidden manner, since [dcl.fct] / 7 illustrates:

The effect of cv-qualifier-seq in a function declaration is not the same as adding cv-qualifier on top of a function type. c In the latter case, the cv qualifiers are ignored. [Note: the type of function that has cv-qualifier-seq is not a cv-qualified type; No CV-qualified function types. - end note] [Example:

 typedef void F(); struct S { const F f; // OK: equivalent to: void f(); }; 

- end of example]

There is no way in the language to form the type of a const function. And yet, we need to output the output of const T as void() . The first type is of type const, and it must also be functional. But this is the type that cannot exist! So how can this be done ?!

On the other hand, the standard has a mechanism to display it if you used a link instead of a pointer.

So it is not clear how this should be allowed. On the one hand, the wording today does not allow this, but, on the other hand, a mechanism for links already exists for this. Therefore, some implementations go and do the same for pointers.

+9
source share

All Articles