Consider the following example:
struct S {
template< typename T >
operator T () {
std::cout << __PRETTY_FUNCTION__;
return T{};
}
};
int main() {
S s{};
const int& x = s;
}
From my reading of the standard I get T = const int
.
But gcc and clang say that T will be deduced to be of type int
. Demo.
From [temp.deduct.conv]:
Template argument deduction is done by comparing the return type of the conversion function template (call it P) with the type specified by the conversion-type-id of the conversion-function-id being looked up (call it A) as described in [temp.deduct.type].
I deduce that A = const int&
and P = T
.
Now clause 4:
- If A is a cv-qualified type, the top-level cv-qualifiers of A's type are ignored for type deduction. If A is a reference type, the type referred to by A is used for type deduction.
Now first, A
is not cv-qualified. Then second, A
is a reference type and therefore I remove &
from A
and get deduced A = const int
.
Now I compare deduced A = const int
with T
and get T = const int
.
My Question: Why the deduced template argument is int
and not const int
as I expect?
This is an (extended) summary of the comments of me and others.
The standard (C++26 draft) seems to be unclear for this example. It can be read in a way that const int
is deduced, or that int
is deduced. Clang has the following comment in its source:
// We work around a defect in the standard here: cv-qualifiers are also
// removed from P and A in this case, unless P was a reference type. This
// seems to mostly match what other compilers are doing.
Clang removes const
after removing the references from A
, and thus deduces int
.
There is a github issue exactly for this example: https://github.com/cplusplus/draft/issues/5123
(Note: I am not sure, whether github issues are officially considered by the C++ standard committee)
There are similar "official" core issues: