I did some further experimentation on the topic of my previous question and have another one.
Consider the code below where, as I expeded, both l_ref are r_ref are const:
#include <string>
#include <iostream>
struct Func
{
void operator()() const
{
static_assert(!std::is_const_v<decltype(v)>);
static_assert(std::is_same_v<decltype(v), std::string>);
static_assert(std::is_same_v<decltype(this), const Func*>);
auto& l_ref = v;
static_assert(std::is_same_v<decltype(l_ref), const std::string&>);
//my idea was that it does not move because it is const r-value reference
auto&& r_ref = std::move(v);
static_assert(std::is_same_v<decltype(r_ref), const std::string&&>);
std::cout << "v: " << v;
}
std::string v;
};
Now consider the following lambda were wired things start to happen and l_ref and r_ref are not const:
int main()
{
std::string v = "abc";
auto func = [v]()
{
static_assert(!std::is_const_v<decltype(v)>);
static_assert(std::is_same_v<decltype(v), std::string>);
auto& l_ref = v;
static_assert(std::is_same_v<decltype(l_ref), std::string&>);
auto&& r_ref = std::move(v);
static_assert(std::is_same_v<decltype(r_ref), std::string&&>);
//what happens here?
auto a = std::move(v);
static_assert(std::is_same_v<decltype(a), std::string>);
std::cout << "v: " << v;
};
func();
return 0;
}
v should not move at line auto a = std::move(v); because lambda is not mutable so it is something similar to void operator() const of the struct Func, but at the same time v is not const and std::move(v) is non-const r-value reference, so what mechanism prevents move constructor of std::string from being called?