Подтвердить что ты не робот

Какая точная семантика удаленной функции в С++ 11?

struct A
{
    A();

    A(const A&);
    A& operator =(const A&);

    A(A&&) = delete;
    A& operator =(A&&) = delete;
};

struct B
{
    B();

    B(const B&);
    B& operator =(const B&);    
};

int main()
{
    A a;
    a = A(); // error C2280

    B b;
    b = B(); // OK
}

Мой компилятор - это VС++ 2013 RC.

ошибка C2280: 'A & A:: operator = (A & &)': попытка ссылаться на удаленная функция

Мне просто интересно, почему компилятор не пытается A& operator =(const A&);, когда A& operator =(A&&) удален?

Является ли это поведение определенным стандартом С++?

4b9b3361

Ответ 1

a = A(); // error C2280

Выражение справа является временным, что означает, что он будет искать operator=(A&&) и видит, что он удален. Отсюда и ошибка. Дальнейшего поиска больше нет.

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

Вот еще один пример. Если я хочу, чтобы экземпляры моего класса X были созданы только с long, и другого типа (даже если он преобразуется в long!), Я бы объявил class X как:

struct X
{
     X(long arg); //ONLY long - NO int, short, char, double, etc!

     template<typename T>
     X(T) = delete;
};

X a(1);  //error - 1 is int 
X b(1L); //ok    - 1L is long

Это означает, что разрешение перегрузки выполняется до того, как компилятор увидит =delete part — и, следовательно, приводит к ошибке, поскольку выбранная перегрузка найдена удаленной.

Надеюсь, что это поможет.

Ответ 2

Когда вы =delete выполняете функцию, вы фактически удаляете ее определение.

8.4.3 Удаленные определения [dcl.fct.def.delete]

1 Определение функции вида:

атрибут-спецификатор-seqopt decl-specifier-seqopt declarator = delete;

называется удаленным определением. Функция с удаленным определением также называется удаленной функцией.

Но тем самым вы также объявляете эту функцию. Цитирование из стандарта [1]:

4 Удаленная функция неявно встроена. [Примечание. Правило с одним определением (3.2) применяется к удаленным определениям. -end note] Удаленное определение функции должно быть первым объявлением функции [...]

И поэтому, делая a = A(), компилятор фактически разрешает A::operator=(A&&), потому что он был объявлен (не A::operator(const A&), потому что A&& является "более привязкой" к r-значениям). Однако, когда его определение будет удалено, линия плохо сформирована.

2 Программа, которая ссылается на удаленную функцию неявно или явно, кроме объявления, плохо сформирована.


[1] Тон подчеркнутого предложения здесь действительно необходим. В стандарте указывается, что объявление функции =delete d должно сначала отображаться перед другими объявлениями. Тем не менее, он поддерживает тот факт, что удаление функции также объявляет функцию.