Возможно ли написать наследника от 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 шт):

Автор решения: HolyBlackCat

Это сводится вот к чему:

non_move_string a;
non_move_string b(std::move(a)); // Ошибка.

Компилятор пытается вызвать перемещающий конструктор и не может, потому что он удален.

Лечится убиранием =delete-нутых перемещающих операций. Еще забыли добавить =default копирующее присваивание.

Перемещающие операции пропадут автоматически, потому что явно созданы копирующие. Но теперь компилятор не будет пытаться их вызвать, а будет заменять копирующими.


Что интересно, libstdc++ принимает этот код, а libc++ и MSVC-шная стандартная библиотека - нет. Видимо специальную проверку прикрутили.

→ Ссылка
Автор решения: AR Hovsepyan

Во первых, хоть и 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){}    
};
→ Ссылка