Возможно ли написать наследника от std::string, запретив ему оператор перемещения и конструктор перемещения? С++
Хочу потестить функцию push_back с копированием и с перемещением. Но пока зашёл в тупик с использованием std::string. Данный код не компилируется.
#include <iostream>
#include <string>
#include <vector>
#include <chrono>
using namespace std;
class non_move_string : public string
{
public:
using string::string;
non_move_string(non_move_string&& other) = delete;
non_move_string& operator=(non_move_string&& other) = delete;
non_move_string(const non_move_string& other) = default;
};
class move_string : public string
{
public:
using string::string;
};
int main()
{
vector<non_move_string> vec_copy;
vector<move_string> vec_move;
auto begin = std::chrono::steady_clock::now();
for (int i = 0; i <= 100000; i++) {
non_move_string tmp("fegerggergerrgrogiergijrgiugjijrvipjfeikq0zdo0ehdoqdocjkovjer9gur9gujiopvbjrpfjrepguj90ghgerg");
vec_copy.push_back(tmp);
}
auto end = std::chrono::steady_clock::now();
auto elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - begin);
std::cout << "The time: " << elapsed_ms.count() << " ms\n";
begin = std::chrono::steady_clock::now();
for (int i = 0; i <= 100000; i++) {
move_string tmp("fegerggergerrgrogiergijrgiugjijrvipjfeikq0zdo0ehdoqdocjkovjer9gur9gujiopvbjrpfjrepguj90ghgerg");
vec_move.push_back(tmp);
}
end = std::chrono::steady_clock::now();
elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - begin);
std::cout << "The time: " << elapsed_ms.count() << " ms\n";
}
Ответы (2 шт):
Это сводится вот к чему:
non_move_string a;
non_move_string b(std::move(a)); // Ошибка.
Компилятор пытается вызвать перемещающий конструктор и не может, потому что он удален.
Лечится убиранием =delete-нутых перемещающих операций. Еще забыли добавить =default копирующее присваивание.
Перемещающие операции пропадут автоматически, потому что явно созданы копирующие. Но теперь компилятор не будет пытаться их вызвать, а будет заменять копирующими.
Что интересно, libstdc++ принимает этот код, а libc++ и MSVC-шная стандартная библиотека - нет. Видимо специальную проверку прикрутили.
Во первых, хоть и std::string конструируется с const char*, ваш производный класс не имеет такого конструктора, во вторых, просто пишите соответствующие конструкторы, а не удаляйте их:
using std::string;
class non_move_string : public string
{
public:
non_move_string(const char* str) : string(str){}
non_move_string(const non_move_string&) = default;
non_move_string& operator=(const non_move_string& other)
= default;
non_move_string(const non_move_string&& other) noexcept
: non_move_string(other){}
non_move_string&
operator=(const non_move_string&& other) noexcept
{
*this = other;
return *this;
}
};
class move_string : public string
{
public:
move_string(const char* str) : string(str){}
};