Template argument deduction fails on MSVC: bug?
The following fails to compile on VC++8.0 complier with an error (I haven't tried it on the latest visual studio complier yet.)
error C2440: 'return' : cannot convert from 'const char *' to 'const char (&)[6]'
template <typename T>
inline T const& compare (T const& a, T const& b)
{
return a < b ? b : a;
}
int main()
{
::compare("string1", "string2");
}
Inside the function template, it seems strings are const char (&)[6]
.开发者_StackOverflow中文版
As far as i know, when <
operator is applied, array should be decayed to pointer.
So, could this error be because of a possible bug?
It is most certainly a bug in the Microsoft compiler.
Here is one big difference in C and C++.
e0 ? e1 : e2
In C++, a condtional-expression produces lvalue, unless at least one of the expressions in the second part (after '?'
) is an rvalue, while in C, a conditional-expression always produces rvalue, no matter what. That means, the following code is perfectly valid in C++ but it is an error in C:
int a=10, b=20;
(a<b?a:b) = 100; //ok in C++, but error in C
In C++, it would not give any error, precisely because the expression(a<b?a:b)
is lvalue expression, so as you can put it on the left side of an assignment.
Now coming back to the original question. In your case, a
and b
are arrays of type char (&) [6]
, and the expression a<b? a : b
should produce an lvalue, as there is no need of array-to-pointer conversion. But in Microsoft compiler, it seems there is array-to-pointer conversion.
To verify it, one can write this:
template <typename T, int N>
inline void f(T const (&a)[N]) {}
template <typename T>
inline T const& compare (T const& a, T const& b)
{
f(a < b ? b : a); //is the argument `char*` OR `char (&)[6]`?
return a < b ? b : a;
}
And it gives no error either (in GCC), which means the expression which you pass to f()
is an array, not a pointer.
As far as i know, when
<
operator is applied, array should be decayed to pointer.
That's the problem, it is being decayed into a const char *
but then it is trying to convert that into const char [8]
for the return value.
I'm not sure what the standard says about this, but if you change it to either:
compare<char *>("string1","string2");
or
compare(static_cast<const char *>("string1"),static_const<const char *>("string2"));
Then the template parameter T
will be char *
instead char [8]
.
精彩评论