
Adam Merz <adammerz <at> hotmail.com> writes:
Jeffrey Lee Hellrung, Jr. <jeffrey.hellrung <at> gmail.com> writes:
<snip> By this logic,
void f(int&); void f(...) f(i++)
should also fail to compile, no?
I would think that the failure of an int rvalue to initialize either an int& or an int const volatile & would simply drop that overload from consideration.
I was so focused on whether it would be legal to call `void g(int const volatile&)` with an int rvalue that I completely forgot about the ellipsis overload. :-P I agree with you completely -- in this context `void g(T)` should be discarded during overload resolution and `void g(...)` should be called. Forgive my oversight -- this is definitely a bug in the Intel compiler.
I take that back -- the Intel compiler is right, GCC and MSVC are wrong. My earlier post focused on whether calling `void g(int const volatile&)` with an int rvalue would be legal (it isn't), but that was partially misplaced -- the relevant part of the standard is overload resolution. Starting from the top, quoting the C++03 standard, §13.3.3.1/3:
A well-formed implicit conversion sequence is one of the following forms: - a standard conversion sequence, - a user-defined conversion sequence, or - an ellipsis conversion sequence.
§13.3.3.2/2:
When comparing the basic forms of implicit conversion sequences - a standard conversion sequence is a better conversion sequence than a user-defined conversion sequence or an ellipsis conversion sequence, and - a user-defined conversion sequence is a better conversion sequence than an ellipsis conversion sequence.
§13.3.3.1.4 repeats multiple times that for the case where the parameter type is a reference, that a standard conversion is taking place; however I won't quote all that here. So with the overloads: void g(int const volatile&); void g(...); When calling g with an int rvalue, the compiler must select the `void g(int const volatile&)` overload because "a standard conversion sequence is a better conversion sequence than a user-defined conversion sequence or an ellipsis conversion sequence". Only then does the compiler decide that calling `void g(int const volatile&)` with an int rvalue is illegal. And this is not without precendence -- quoting §13.3.3.1.4/4:
Other restrictions on binding a reference to a particular argument do not affect the formation of a standard conversion sequence, however. [Example: a function with a "reference to int" parameter can be a viablecandidate even if the corresponding argument is an int bit-field. The formation of implicit conversion sequences treats the int bit-field as an int lvalue and finds an exact match with the parameter. If the function is selected by overload resolution, the call will nonetheless be ill-formed because of the prohibition on binding a non-const reference to a bit-field.]
Summary: Intel *is correct* according to the standarde, but GCC and MSVC take the sane/practical route.