27

Consider the following example (godbolt):

#include <iostream> template <typename T> const T *as_const(T *p) { return p; } void f() {} template <typename T> void g(T *) { std::cout << "A"; } template <typename T> void g(const T *) { std::cout << "B"; } int main() { g(as_const(&f)); } 

Both GCC and Clang can compile it, but the resulting executables produce different output: the version compiled with GCC prints A and the one compiled with Clang prints B.

Could you explain this difference?

Update: as pointed out by @VTT the same difference is observed even if as_const is dropped.

13
  • 6
    I'm not sure what a pointer-to-const-function actually means or how it differs from a non-const-pointer-to-function. Commented Jan 3, 2018 at 18:25
  • 2
    Visual studio outputs 'B' Commented Jan 3, 2018 at 18:29
  • 3
    as_const is irrelevant for this example. Commented Jan 3, 2018 at 18:36
  • 1
    Pretty sure you can't have pointers to const function types. See N4141 8.3.5/6 and 8.3.1/4. Commented Jan 3, 2018 at 18:38
  • 3
    @ChristianHackl I don't undersatnd why you think that this is an ODR violation; the functions have two different signatures, and template deduction + overload rules will lead to exactly the intuitive behavior if you are working with pointers to objects (rather than to functions). Commented Jan 3, 2018 at 18:53

1 Answer 1

17

It appears you hit a defect in the standard which has yet to be resolved. So the answer to "Which compiler is right?" would be not entirely clear currently.

The issue has been raised to and discussed by the committee:

It is not clear whether the following is well-formed or not:

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

Implementations vary in their treatment of this example.

see http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1584, but the proposed resolution is not part of N4141 or N4659.

Note that you generally cannot have pointers to const function types; if you consider the example I quoted ill-formed, gcc would be correct. It does reject the example and, in the OP, picks the non-const version as the only viable overload.

If clang (which claims to implement the proposed resolution) would be right otherwise, I am not sure. I guess we'd have to revisit that discussion once the committee resolved the issue with some normative wording we can use.

However,

The consensus of CWG was that the cv-qualification of the argument and parameter must match, so the original example should be rejected.

(note to said issue) seems to indicate that gcc is right and the issue will be resolved in favor of its behavior.

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

1 Comment

Might be worth mentioning explicitly that gcc does in fact fail to compile that example; gcc could in principle give the non-const g priority, but still compile the const qualified pointer version if the other were unavailable.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.