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?