13

g++ 4.8.1 and clang++ 3.4 give different results for next code:

// simplified code from a Logger module #include <iostream> template<class T> void tf(const T*) { // clang++ std::cout << "void tf(const T*)\n"; } template<class T> void tf(T) { // g++ std::cout << "void tf(T)\n"; } int main(){ typedef std::ios_base& (*ph)(std::ios_base&); ph p = std::hex; tf(p); // or just tf(std::hex) } 

I can't figure out which variant is correct (C++ 03).

2
  • 2
    I think the question boils down to this : Is auto const * p = std::hex; allowed? GCC says NO but Clang says YES. So who is right? Commented Oct 2, 2013 at 7:11
  • if you add a template<class T> tf(T*) overload, then g++ will selec that one, but clang keeps going for the const T* overlaod. Commented Oct 2, 2013 at 7:55

2 Answers 2

6

A pointer to function is not a pointer to an object and talking about const-ness of a pointer to function doesn't make sense in C++.

IMO g++ is right because hex qualifies as a pointer to function, but not as a const * to anything.

In the first case the template parameter is not a "pointer" but a "pointer to object".

There's no such a thing as a generic "pointer" in C++... you have pointers to function, pointers to object or pointer to members. Each of the three has different rules and is incompatible with the others.

Admittedly the null pointer brings in some confusion...

Sign up to request clarification or add additional context in comments.

6 Comments

But p is a pointer, so the first overload seems to be more specialized, from pointer point of view (no pun intended). I'm confused.
@Nawaz: A pointer to function is not a pointer to an object. They're different and incompatible types. You can convert a pointer to function to another pointer to function and back, but not to a pointer to object (or even void *) and back. A const * to function of course doesn't make any sense (like also doing pointer arithmetic on it)... those things work only for pointer to objects. The template parameter of the first version is not a "pointer", but a "pointer to an object".
So, does clang++ make an error when deducing template arguments? Deduction should fail for template<class T> void tf(const T*).
@gruzovator: simply that argument is not compatible with that template so the compiler should pick the second one like g++ does. This is what is called SFINAE "Substitution Failure Is Not An Error" and it's one of the main weapons in template metaprogramming (it has been used to build great stuff and to commit great crimes).
@gruzovator: Exactly. A const T* is not compatible with a function pointer, so that template specialization doesn't apply.
|
4

I've tried to submit this as a bug to llvm bugzill. The answer was:

This is a GCC bug. See:

http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1584

1 Comment

Are you sure this view has been accepted in the standard? What you're linking is IIUC just a proposal to take a position. I personally think that matching a function pointer to an object pointer template parameter is highly questionable.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.