Recently, I came across own code that I wrote accidently this way (much simplified here):
#include <iostream>
#include <string>
void foo(std::string&& value)
{
std::cout << value << std::endl;
// for instance modify value here somehow optionally and move it further on ...
// foo2(std::move(value));
}
int main()
{
std::string value = "Hello world";
for (size_t idx = 0; idx < 2; ++idx)
{
foo(idx < 1 ? value : std::move(value));
}
}
Please no comments about the questionable scheme at all! This happened during a long night session... :)
I just want to know, what's actually going on here in terms of standard behavior. Type deduction of the ternary operator leads to an rvalue obviously, but I'd like to know the exact fitting phrase(s) within the standard since the observable effect is such that for the idx < 1 case, an rvalue to a copy(?) of value is produced.
I read https://timsong-cpp.github.io/cppwp/n4659/expr.cond but that doesn't seem to be enough to explain the behavior here since I expected a direct rvalue conversion (originally, I expected a compiler error though). I also thought there might be some duplicates here on SO about this but I wasn't able to find the really fitting one(s) here so far. So sorry in advance if there are quite fast detectable ones however!
According to cppinsights.io the compiler is creating a temporary
std::string
.And here the version that separates the ternary operator from the function call:
cppinsights.io says
I am trying to understand that reading the standard n4835.pdf, I hope this is correct:
4.1 and 4.2 do not apply, so we are coming to 4.3.3. and there to 7.3.1 where 3.2 applies.
Please note that 7.6.16 4 says that conversions are tried in both directions, thus don't focus too much on the "E2" in 4.3(.3).