I have code here:
#include
#include
#include
template
class Test
{
public:
Test(std::initializer_list l)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
Test(const Test& copy)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
Test(Test&&) = delete;
Test() = delete;
};
void f(const Test>& x)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
void f(const Test& x)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
f(Test>{x});
}
int main()
{
Test t1 {"lol"};
f(t1);
return 0;
}
I try to compile this with GCC 7.3.0 on my linux mint 19 with command:
g++ -std=c++11 -O0 test.cpp -o test -Wall -pedantic
Compilation fails with error that this call:
f(Test>{x});
Requires move constructor, but it's deleted. I always thought that move and copy constructors are equivalent in terms of compilation cause rvalue can be bound to const reference, but overload with explicitly defined rvalue reference is just prioritized in overload resolution. This is first time i see that compiler actually requires move constuctor and won't just use copy instead. Why? Am i missing something?
Answer
You declared the move constructor explicitly and marked it as delete
, it'll be selected by overload resolution, and then cause the error.
If both copy and move constructors are provided and no other constructors are viable, overload resolution selects the move constructor if the argument is an rvalue of the same type (an xvalue such as the result of std::move
or a prvalue such as a nameless temporary (until C++17)
), and selects the copy constructor if the argument is an lvalue (named object or a function/operator returning lvalue reference).
Note that the deleted implicitly-declared move constructor is ignored by overload resolution, but the explicitly-declared one won't.
The deleted implicitly-declared move constructor is ignored by overload resolution (otherwise it would prevent copy-initialization from rvalue). (since C++14)
No comments:
Post a Comment