I was wondering if a copy elision is made in the call of foo(string) below.
(Note: foo(string) belongs to an interface that I can not change ).
For this I attempted to check whether constructed string("Hello world!") is a rvalue.
I search on SO how to do this programmatically and found this post
void foo( string str)
cout << str << endl;
cout << is_rvalue_reference<decltype(string("Hello world!"))>::value << endl;
- Where am I wrong?
std::string("") is an rvalue, but
decltype(std::string("")) is not an rvalue reference. The type of a
std::string object is ...
std:string, of course.
You have a category error. An rvalue is a kind of expression, an rvalue reference is a kind of type.
string object is an rvalue. The type
string&& is an rvalue reference type.
decltype expression is not useful for what you're trying to do. Consider:
std::string s; using type1 = decltype(s); using type2 = decltype(std::string("")); static_assert(std::is_same<type1, type2>::value, "same");
In both these cases
decltype gives the same type:
std::string. That's because
decltype tells you about types, not value categories (i.e. whether an expression is an rvalue or an lvalue).
If you want to know whether an expression is an rvalue or an lvalue you need to know more than just its type. In the case of
decltype(std::string("")) you are creating an unnamed temporary, which is an rvalue. You don't need to ask its type to know that.
- string("Hello world!") may be a rvalue but does not seem to be a "reference of any kind" (either lvalue, rvalue, universal ... ) so that I got false result. Is there a way to get a true answer in case of a rvalue ?
What do you mean by "true" answer? Do you just mean a type trait that will give the result
You can ask if the type is convertible to an rvalue reference:
That will tell you if you can bind an rvalue reference to the object. But it's a silly question: of course you can bind an rvalue reference of type X&& to a temporary of type X. You would never need to ask that.
And anyway, you function doesn't take an argument of type
string&& so asking that question doesn't even tell you anything about your call to
- Is there copy elision or not in his example ?
Yes, initializing the function argument from a temporary string should not make any copies or moves, they should be elided. The C++14 standard says in [class.copy] p31 that a copy/move can be elided when a temporary object (that has not been bound to a reference) would be copied/moved to a class object of the same type. That condition is met when initializing a function argument of class type from a temporary of the same type. A compiler that doesn't perform that elision (at least when optimisations are enabled, or in "release" builds) is a bad compiler.
There is an explanation of the copy elision rules at http://en.cppreference.com/w/cpp/language/copy_elision -- see the part about a nameless temporary.