Самый краткий способ отключить семантику копирования и перемещения

следующее, конечно, работает, но очень утомительно:

T(const T&) = delete;
T(T&&) = delete;
T& operator=(const T&) = delete;
T& operator=(T&&) = delete;

Я пытаюсь найти самый краткий способ. Будут следующие работы?

T& operator=(T) = delete;

обновление

обратите внимание, что я выбираю T& operator=(T) вместо T& operator=(const T&) или T& operator=(T&&), потому что он может служить обеим целям.

5 ответов


согласно этой диаграмме (Говард Хиннант):

meow

самый краткий путь =delete оператор назначения перемещения (или конструктор перемещения, но это может вызвать проблемы, упомянутые в комментариях).

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


Я предпочитаю наследовать от boost:: noncopyable, тем самым делая намерение немедленно ясным и делегируя детали надежной библиотеке.

#include <boost/core/noncopyable.hpp>

class X: private boost::noncopyable
{
};

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


пожалуйста, не пытайтесь найти "самый краткий способ" написать фрагмент кода.

Если нет очевидной формы выражения чего - то, что также очень лаконично-Не ищите, не пытайтесь формулировать-адвокат Ваш путь к написанию нескольких символов меньше. Почему? Подумайте о людях, читающих ваш код:

Если вам нужно проконсультироваться со стандартом, чтобы понять, что ваш код делает то, что вы хотите, чтобы он делал - то и читатели вашего кода. Только они не поймут, что ты пытаешься сделать. чтобы достичь; поэтому они не будут консультироваться со стандартом; поэтому они просто будут смущены тем, что делает ваш код. Или-кто-то получит, а кто-то нет.*1

в вашем случае, если вы сделаете подмножество этих удалений или используете какой - то другой "умный" трюк-как человек, читающий ваш код, я, скорее всего, не поймаю, не замечу, что вы на самом деле пытаетесь удалить всю семантику копирования и перемещения. И я запутаюсь, думая, что ты пытаешься сделать что-то еще. На самом деле, если я будь вы, я бы даже подумал добавить комментарий, говоря:

/* Disabling copy and move semantics because XYZ */
T(const T&) = delete;
T(T&&) = delete;
T& operator=(const T&) = delete;
T& operator=(T&&) = delete;

что еще более "утомительно", но сделает ваше намерение/мотивацию абсолютно ясными для ваших будущих читателей.

существует также вопрос о том, что именно является причиной "XYZ". Некоторые утверждают, что нет веских причин удалять члены move, и это, как правило, плохая идея сделать это. C++ luminary Говард Хиннант имеет сказал по этому вопросу.

* - A вариант по принципу я прописал здесь.


вы можете написать простой struct и наследовать от него:

struct crippled
{
    crippled() = default;

    crippled(const crippled&) = delete;
    crippled(crippled&&) = delete;

    crippled& operator=(const crippled&) = delete;
    crippled& operator=(crippled&&) = delete;
};

использование:

struct my_class : crippled
{

};

int main()
{
    my_class a;
    auto b = a; // fails to compile
}

Я считаю, что в этом случае макросы на самом деле более читабельным:

#define NOT_COPYABLE( TypeName ) \
TypeName ( TypeName const& ) = delete; \
TypeName & operator = ( TypeName const& ) = delete;

#define NOT_MOVEABLE( TypeName ) \
TypeName ( TypeName && ) = delete; \
TypeName & operator = ( TypeName && ) = delete;