2015-04-16 1 views
2

Рассмотрим этот класс:Какова спецификация исключения для операции перемещения по умолчанию, определенной вне класса?

class C1 { 
    C1(C1&&) = default;  // declare and define move ctor 
}; 

Поскольку движение С1 т е р является явно дефолт по своей первой декларации, 8.4.2 стандарта говорит нам, что это имеет спецификацию же исключение (ES), как если бы функция была объявлена ​​неявно , Затем мы можем использовать 15.4/14 и 12.8/15, чтобы сделать вывод, что его ES равен noexcept(true).

Теперь рассмотрим класс С2, который является тем же самым, за исключением его перемещения CTOR устанавливается по умолчанию вне определения класса:

class C2 { 
    C2(C2&&);     // declare move ctor 
}; 

C2::C2(C2&&) = default;  // define move ctor 

Что такое ES для перемещения CTOR С2 в? Поскольку он не дефолт по первому объявлению, 8.4.2/2 не применяется. Поскольку он не имеет явного ES, 8.4.2/3 не применяется. Поскольку это неявно объявлено, 15.4/14 не применяется. Из того, что я могу сказать, это означает, что применяется 15.4/12, и в нем говорится, что функция по умолчанию ES равна noexcept(false).

Если я прав, это означает, что перемещение ctor в C1 равно noexcept(true), но концептуально идентичный ход ctor в C2 равен noexcept(false).

Является ли мое рассуждение о C2 правильным?

+0

глядя на [черновик] (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3376.pdf), я не вижу, где он указывает, что ему нужно для дефолта по первой декларации ** **. Размышление об этом? –

+0

Проверьте 8.4.2/2 и 8.4.2/3 спецификации C++ 14. – KnowItAllWannabe

+1

Разница между ними состоит в том, что 'C2 :: C2 (C2 &&) = default;' может находиться в другой единицы перевода (и на самом деле должна быть ровно одна единица перевода). Код, который видит только декларацию 'C2 (C2 &&);', не имеет другого выбора, кроме как предполагать худшее). С другой стороны, определение 'C1' должно быть полностью повторено в каждой единицы перевода (в рамках ODR), поэтому любой, кто ее использует, может –

ответ

6

Да, ваша интерпретация верна, и если вы сделаете ваши заявления общественности, легко показать, что оба лязг и ССАГПЗ согласны с рассуждениями:

#include <type_traits> 

class C1 
{ 
public: 
    C1(C1&&) = default;  // declare and define move ctor 
}; 

class C2 { 
public: 
    C2(C2&&);     // declare move ctor 
}; 

C2::C2(C2&&) = default;  // define move ctor 

int 
main() 
{ 
    static_assert(std::is_nothrow_move_constructible<C1>{}, ""); 
    static_assert(!std::is_nothrow_move_constructible<C2>{}, ""); 
} 
1

интерпретация верна, то да. Упорядочение после первого объявления означает создание тела функции без выполнения магии в объявлении. Если определение находится в другом ЕП, вы можете свободно переключаться между

C2::C2(C2&& rhs) {/* hand-written implementation here */} 

и

C2::C2(C2&& rhs) = default; 

и что не видно пользователям класса. Так как вы не указали по умолчанию в первом объявлении, объявление эффективно noexcept (false) и (к лучшему или худшему) остается таким образом независимо от подобъектов в вашем классе. По умолчанию, когда первая декларация вступает в «волшебство» в этом , может быть сгенерирована спецификация noexcept вашего объявления.

+0

ah, за исключением того, что даже специальная функция-член по умолчанию после первого объявления (ака за пределами определения класса) должна соответствовать неявному определению в отношении спецификации noexcept. –

Смежные вопросы