2014-09-18 2 views
10

Почему static_assert должен быть вне определения класса?static_assert определение внутри/снаружи класса

В противном случае код

#include <type_traits> 

class A 
{ 
public: 
    A(A&&) noexcept {} 
    static_assert(std::is_nothrow_move_constructible<A>::value, "ERROR"); 
}; 

int main() 
{ 
} 

Рабочий код

#include <type_traits> 

class A 
{ 
public: 
    A(A&&) noexcept {} 

}; 

static_assert(std::is_nothrow_move_constructible<A>::value, "ERROR"); 

int main() 
{ 
} 

И когда уместно использовать static_asserts в определении класса или структуры?

+0

Что не работает в первую очередь? Есть ли сообщение об ошибке? – 0x499602D2

+0

Я редактировал заголовок вопроса для соответствия содержимому вопроса. – aschepler

+0

@ 0x499602D2 Неисправный код дает это сообщение при компиляции с г ++ --std = C++ 11 {код} is_nothrow_move_constructible.cpp: 8: 1: ошибка: статическое утверждение не выполнено: ОШИБКА static_assert (станд :: is_nothrow_move_constructible :: значение «ОШИБКА»); {code} – Parkesy

ответ

17

Что касается размещения самого static_assert, то обе версии вашего кода действительны. Таким образом, нет, static_assert не должно быть вне определения класса. Формально static_assert является заявкой . Это разрешено везде, где допускаются объявления.

Проблема, с которой вы сталкиваетесь, не имеет отношения к static_assert.

Проблема здесь состоит в том, что выражение, которое вы используете в качестве аргумента вашего static_assert (std::is_nothrow_move_constructible) требует тип класса, чтобы быть полный работать должным образом. Но внутри определения класса A класс типа A еще не завершен, что делает ваше выражение аргумента недействительным. Вот почему ваш static_assert работает по назначению только за пределами определения класса, где A завершено. Тем не менее, это полностью касается правильного использования std::is_nothrow_move_constructible, а не около static_assert.

Обратите внимание, что внутри класса объектов-членов функции класса видны полностью, как полный тип, даже если функция-член определена внутри определения класса. С помощью этой функции вы можете переписать код, как

class A 
{ 
public: 
    A(A&&) noexcept { 
     static_assert(std::is_nothrow_move_constructible<A>::value, "ERROR"); 
    } 
}; 

и std::is_nothrow_move_constructible<A> произведут должный результат.

+0

И, AFAIK, 'static_assert' может * использоваться внутри тела функции * –

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