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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With