Topic: Rvalues and qualifiers


Author: CornedBee <wasti.redl@gmx.net>
Date: Sun, 25 Oct 2009 10:56:51 CST
Raw View
Hi,

C++03 [basic.lval]p9 (and also the most recent working draft):
"Class rvalues can have cv-quali   ed types; non-class rvalues always
have cv-unquali   ed types."

In C++03, this peculiar rule was essentially irrelevant. Making
rvalues of class types carry qualifiers means this:

struct S { void nonconst(); };
const S cs();

void foo() { cs().nonconst(); /* invalid */ }

This is important.
Making rvalues of non-class types *not* carry qualifiers, on the other
hand, is completely undetectable. It isn't even noticeable in
overloading, since top-level cv qualifiers in function parameters do
not participate in overloading rules. The qualifier conversion is
subsumed in the initialization of the parameter.

So we have a very unintuitive rule in the standard, but no one cares,
because it isn't noticeable. For all practical purposes, all rvalues
carry qualifiers.

Until C++0x. Because now we have at least two ways I'm aware of that
detect this distinction: decltype and rvalue references.

---------------------------------------
const int ci();
const std::string cs();
void f(int&&);
void g(std::string&&);

void test()
{
   // the comma expressions prevent the special rule for function calls
   decltype((0, cs())) vs; // type is const std::string.
   vs = "Hello"; // invalid
   decltype((0, ci())) vi; // type is int
   vi = 0; // valid

   f(ci()); // valid
   g(cs()); // invalid
}
---------------------------------------

Try to explain this to the average C++ programmer.

What's the rationale behind this rule? For all I can see, it's a
misguided attempt to keep C compatibility, where rvalues never carry
qualifiers. But I don't think C has any way to detect this, so I don't
understand why this would be relevant. In C++0x, however, this rule
leads to hard-to-explain behavior that holds little advantage to
anyone - it makes the language harder to understand and to implement.
The only advantage that I see is that there needs to be no reasoning
about cv-qualifiers in operators, e.g.

---------------------------------------
const int ci = 100;
int i = 99;

decltype(ci + i) v; // no doubt about the type of this
---------------------------------------

But I feel that the language would be more intuitive if this was
handled for the expressions themselves, i.e. add rules for dropping
top-level cv qualifications to most operators. Notable exceptions are
the comma operator and the conditional operator.


Have I overlooked something?


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Nikolay Ivchenkov <tsoae@mail.ru>
Date: Mon, 26 Oct 2009 00:18:39 CST
Raw View
On 25 Oct, 19:56, CornedBee <wasti.r...@gmx.net> wrote:
> Making rvalues of non-class types *not* carry qualifiers, on the other
> hand, is completely undetectable.

It can be detected via passing as an argument of function template:

template <class T>
      void f(T &);

If the argument is non-const rvalue then f is not viable. If the
argument is const rvalue then f is viable. But there is a problem with
specification of constness of function's return type which I have
considered in
http://groups.google.ru/group/comp.lang.c++.moderated/browse_thread/thread/2bd606664e4371b6#

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]