I have a class with copy constructor and copy assign operator deleted. Move constructor amd move-assign operator are present. It also defines an operator<<
:
struct S
{
S(std::size_t s) {}
S(const S &) = delete;
S(S &&) { std::cout << "S&&"; }
S &operator =(const S &) = delete;
S &operator =(S &&) { std::cout << "=S&&"; return *this; }
S &operator<<(int) { return *this; }
};
Also I've added an user defined literal:
S operator ""_S(const char *const c, std::size_t s)
{
return s;
}
Then I use the S
object like this:
/* Error: */ auto s1 = "Test"_S << 1 << 2 << 3;
/* Ok: */ auto s2 = "123"_S;
.code.tio.cpp:22:20: error: call to deleted constructor of 'S'
/* Error: */ auto s1 = "Test"_S << 1 << 2 << 3;
^ ~~~~~~~~~~~~~~~~~~~~~~~
.code.tio.cpp:7:2: note: 'S' has been explicitly marked deleted here
S(const S &) = delete;
^
I thought that the Error
case would be valid and trigger the operator=(S &&)
since "Test"_S << 1 << 2 << 3
is a temporary expression. Also nothing is printed on the output window but I was expecting to see =S&&=S&&
.
Obviously I'm wrong on all my assumptions, what's happening here?
s1
is not move-asigned from "Test"_S << 1 << 2 << 3
expression?s2
created in-place with the "123"_S
expression thus avoiding the move-assign operator?Why s1 is not move-assigned from "Test"_S << 1 << 2 << 3 expression?
operator<<
returns a reference, but the copy constructor is deleted. You might do something like this
struct S
{
S(std::size_t s) { std::cout << "ctor\n"; }
S(const S &) = delete;
S(S &&) { std::cout << "S&&"; }
S &operator =(const S &) = delete;
S &operator =(S &&) { std::cout << "=S&&"; return *this; }
S operator<<(int) { return std::move(*this); }
// ^ ^^^^^^^^^
};
Which will output1
ctor
S&&S&&S&&ctor