Please, help me understand what's wrong with this piece of code:
#include <string>
#include <utility>
class Sample
{
public:
explicit Sample(std::string data):
_data(std::move(data))
{}
operator const std::string &() const & { return _data; }
operator std::string &&() && { return std::move(_data); }
private:
std::string _data;
};
int main()
{
auto sample1 = Sample{"a"};
const auto sample2 = Sample{"b"};
auto sample3 = Sample{"c"};
auto s1 = std::string{sample1};
auto s2 = std::string{sample2};
auto s3 = std::string{std::move(sample3)};
return 0;
}
The problem is with s3
. The compiler says sth like that:
<source>: In function 'int main()':
<source>:27:45: error: call of overloaded 'basic_string(<brace-enclosed initializer list>)' is ambiguous
27 | auto s3 = std::string{std::move(sample3)};
| ^
In file included from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/string:55,
from <source>:1:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:565:7: note: candidate: 'std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]'
565 | basic_string(basic_string&& __str) noexcept
| ^~~~~~~~~~~~
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:456:7: note: candidate: 'std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]'
456 | basic_string(const basic_string& __str)
| ^~~~~~~~~~~~
Compiler returned: 1
As I understand, both of the operators
for some reason participate in overload resolution for an rvalue. Why is that happening? Should ref-qualifiers leave only one overload for lvalue and the other for rvalue? Am I missing something?
A few other notes:
- The behaviour is different across different compilers/versions. I tested it with godbolt and here is that I found:
- gcc 8.3 and older - compiles fine
- gcc 8.4 and newer - fails to compile
- clang - I couldn't find a version where it compiles
- MSVC - compiles fine on newest versions
- if I refactor operators to normal member functions, it all works as intended
Thank You for Your time, looking forward to any replies :)
Aucun commentaire:
Enregistrer un commentaire