Копировать / переместить исключение против явно удаленных конструкторов копирования / перемещения

Я хочу знать, когда разрешение на копирование / перемещение применяется (или разрешено применять) явно deleted копировать / перемещать конструкторы и неdeleted копировать / перемещать конструкторы. Вот особенности:

  1. Может явно deleteскопировать ctor или переместить ctor? Это попытка создать объект из другого объекта того же типа или временного объекта, который когда-либо позволял добиться успеха, пропуская deleted скопировать ctor и / или deleteпереместить ctor?

    Вот что происходит в VC12 (с которым я не уверен, есть ли возможность отключить копирование / перемещение elision):

    #include <iostream>
    
    struct Foo {
    Foo() { std::cout << "default ctor\n"; }
    Foo(Foo const&) = delete;
    Foo(Foo&&) = delete;
    };
    
    int main() {
    // ----Output------
    Foo{ Foo() };        // "default ctor"Foo f;               // "default ctor"Foo{ std::move(f) }; // error C2280: 'Foo::Foo(Foo &&)' : attempting to reference a deleted function
    Foo{ f };            // error C2280: 'Foo::Foo(const Foo &)' : attempting to reference a deleted function
    }
    

    Хотя IntelliSense жалуется на Foo{ Foo() };: Error: function “Foo::Foo(Foo &&)” ... cannot be referenced – it is a deleted functionкомпилятор там не жалуется, так что строка все еще компилируется.

  2. Почему Foo{ Foo() }; работать, но не Foo{ std::move(f) };? Если один вызов отменяет ход ctor, то не другой?

  3. Почему Foo{ Foo() }; работать, но не Foo{ f };? Эта избирательность выглядит произвольно. Этот вид произвольного предпочтения rvalue-ссылки перед const-ссылкой (или наоборот), похоже, не применяется к не-ctor методам; где в вызове, если deleted перегрузка, которая в противном случае имела бы более высокий приоритет разрешения перегрузки, чемdeleteперегрузка, deleted один блокируетdeleted один, что приводит к ошибке компилятора:

    struct Bar {
    void g(int const&) {}
    void g(int&&) = delete;
    };
    
    //…
    Bar b;
    b.g(2); //error C2280: 'void Bar::g(int &&)' : attempting to reference a deleted function
    // ^ Would have compiled had function `g(int&&)` been commented out.
    

    Согласно этой логике, deleted Foo(Foo&&) не должен блокировать вызов Foo(Foo const&) когда аргумент не является временным; Foo(Foo&&) будет иметь более низкий приоритет разрешения перегрузки, чем Foo(Foo const&) в таком случае.

  4. Я пробовал то же самое Foo пример в g ++ 4.8 с отключенным разрешением копирования (через флаг -fno-elide-constructors) и снова с ним включен. Оба испытания g ++ дали:

    error: use of deleted function 'Foo::Foo(Foo&&)' за Foo{ Foo() }; а также

    error: use of deleted function 'Foo::Foo(const Foo&)' за Foo{ f };

    Какой компилятор правильный?

2

Решение

У MS VC ++ есть очень старая хорошо известная ошибка. Из стандарта C ++

[Примечание: это двухступенчатое разрешение перегрузки должно быть выполнено
независимо от того, будет ли выполнено копирование. Это определяет
конструктор, который вызывается, если elision не выполняется, и выбранный
Конструктор должен быть доступен, даже если вызов отменен. —Конечная записка]
4

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector