Let's consider those definitions:
/*** full type information with typeid ***/
template <class> class Type{};
template <class T> std::string typeStr()
{ return typeid(Type<T>).name(); }
/*** function template for parameter deduction ***/
template <class T> void func(const T &a)
{
std::cout << "Deduced type for T is: " << typeStr<T>() << std::endl;
std::cout << "\targument type is: " << typeStr<decltype(a)>() << std::endl;
}
with pointers to const
If the following statements are executed:
const int i=5, *ip=&i;
func(ip);
The output is:
Deduced type for T is: 4TypeI**PKi**E
So T
is actually deduced as a pointer to a constant integer. The fact that the argument is a reference-to-const does not change the deduction, which is what one would expect because the constness of the pointer is low-level.
but with array of const
Nonetheless, if following statements are executed:
const int ia[3] = {3, 2, 1};
func(ia);
The output is:
Deduced type for T is: 4TypeI**A3_i**E
So T
is actually deduced as an array of 3 non-const integers. The fact that the argument is a reference-to-const does change the deduction, as if the const
was slipping into the array elements.
Actually, versions of CL up to 18 were deducing T
as array of 3 const integers was what I expected to be standard, but it seems that since v19 it converged to what GCC and Clang are doing (i.e., deducing as non-const).
Thus, I assume the later behaviour to be standard, but was is the rationale ? It could seem surprising that it does not behave like with pointers.
Edit: Following dip comment, I will report here pointers to CWG issues related to this behaviour, pointers he actually posted as a comment on this answer (answer that actually raised this new question... C++ feels like a deep tunnel)
- CWG 1059
- CWG 1610
- CWG 112