Re: Rationale of non-const reference to temporaries
On Dec 2, 10:57 am, Dragan Milenkovic <dra...@plusplus.rs> wrote:
Daniel Kr??gler wrote:
On 1 Dez., 20:52, eca <enrico.ecam...@gmail.com> wrote:
[snip]
Now, as your example implies: Sometimes we would really
like the behavior, that the compiler accepts a temporary
as a mutable references (e.g. in those cases, where we
are not interested in the final result of the temporary.
C++0x added so-called rvalue-references which would
make your snippet well-formed:
#include <string>
#include <iostream>
void f(std::string&& s) // <- Note the && here!
{ std::cout << s << std::endl; }
int main(int argc, char* argv[])
{
std::string s("Hello world");
f(s); // <- This is ok
f(std::string("Hello world")); // <- This is *now* also ok!
return 0;
}
... and it still bugs me (referring to the thread "Rvalue-references,
binding and conversions")
const char * const s2 = "Hello world";
const SomethingConvertibleToString s3("Hello world");
const std::string s4("Hello world");
f(s2); // <- This is ok
f(s3); // <- This is ok
f(s4); // <- FAILS!!!
When looking at s2, s3, s4, we see constant values that are, or can be
converted to a string. But why is s4 different because it really _is_
a string? I understand the way things are for lvalue-references,
but not entirely for rvalue-references.
My question is if things work this way because of:
1. A plain technical reason ("if we make it like this, we will get
move semantics and perfect forwarding, else we won't",
or "it reduces the source of errors"), or
2. Is there a more solid logic this is based on? Because my
point of view is that "const SomethingConvertibleToString"
and "const std::string" should be treated in a very similar
way, at least in the context introduced in this thread.
Many thanks to a person who clears things up for me. And sorry if
I'm bothering too much...
I believe it works this way because it is the way C++98 works. I know
that isn't a very satisfying answer. But I believe it is the truth.
I believe I tracked the behavior down to a single sentence in the
current C++0X draft. This sentence also existed in C++98 and C++03.
See [dcl.init.ref], paragraph 5, bullet 2, sub-bullet 3:
If T1 is reference-related to T2, cv1 must be the same
cv-quali???cation as, or greater cv-quali???cation than, cv2;
otherwise, the program is ill-formed.
Earlier in this section "reference-related" is defined to mean when T1
and T2 have the same type. I.e. in your example, the standard singles
out the case when the argument base type is std::string, and doesn't
when the argument is SomethingConvertibleToString. To see this
wording in action in C++98 code consider:
struct B {};
struct string
{
string() {}
string(const volatile string&) {}
string(const volatile B&) {}
};
void
f(const string&)
{
}
int main()
{
volatile B b;
f(b); // ok
volatile string s;
f(s); // fails
}
A volatile B will implicitly convert to an rvalue string, and the call
to f succeeds. A volatile string will also implicitly convert to an
rvalue string. However the call to f fails because volatile string is
reference-related to const string but the argument is not reference-
compatible.
Should this behavior be changed for C++0X? I don't know. It is
easily worked around with:
f(string(s)); // now ok
-Howard
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]