Boost logo

Boost :

Subject: Re: [boost] [type traits extension] test for const volatile& as return type
From: Adam Merz (adammerz_at_[hidden])
Date: 2011-07-07 23:00:37


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.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk