Использование оператора noexcept для цепочки объявлений noexcept

Почему оператор noexcept принимает выражение, а не сигнатуру/декларацию функции?

Рассмотрим следующий фиктивный пример:

#include <string>

void strProcessor(const std::string& str) noexcept(true) { };

struct Type{
  void method1() noexcept(strProcessor("")) { //Error: Call to nonconstexpr function
     strProcessor("");
  }
};

Он не скомпилируется, потому что method1 имеет выражение, отличное от constexpr, в своем noexcept, но зачем мне в первую очередь помещать туда выражение?

Все, что я хочу сделать, это сообщить компилятору, что method1 является noexcept, если и только если вызов strProcessor с успешно созданной строкой является noexcept (что так и есть).

Так почему бы не noexcept(void strProcessor(const std::string&))?

Еще один похожий фиктивный пример:

struct Type{
   Type(bool shouldThrow=false) noexcept(false) { if(shouldThrow) throw "error"; };
   void method1() noexcept(true) {};
   void method2() noexcept(noexcept(Type().method1())) { method1(); };
}

Здесь я хотел бы сказать, что method2 не является исключением, если и только если вызов method1 для успешно созданного экземпляра Type имеет значение noexcept (что в данном случае и есть), но Type даже не завершен в точке, где method2 идентификатор определен.

Пожалуйста, объясните, если я неправильно понимаю эту функцию.


person PSkocik    schedule 27.07.2015    source источник
comment
Ну, здесь есть гибкость, так как тогда вы можете делать более умные вещи, чем просто называть функцию. Выражение не будет оцениваться, поэтому вы можете использовать declval и друзей, чтобы избежать побочных эффектов и т. д. Я действительно не понимаю ошибку, хотя я не слишком горяч ни к noexcept, ни к constexpr.   -  person Lightness Races in Orbit    schedule 27.07.2015


Ответы (2)


void method1() noexcept(noexcept(strProcessor(""))) {
//   Second 'noexcept'  ^^^^^^^^^                ^

Первый — это noexcept спецификатор, который < strong>указывает, является ли method1() noexcept.

Вложенным является noexcept оператор, который < strong>проверяет, является ли strProcessor() noexcept при вызове с "".

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

void method2() noexcept(noexcept(
    (std::declval<Type>().*&Type::method1)()
)) {};

Однако я не думаю, что есть случай, когда вы можете вывести спецификацию noexcept method2() только из спецификации method1().

person Quentin    schedule 27.07.2015
comment
Спасибо! Можете ли вы исправить второй пример? - person PSkocik; 27.07.2015

Если вам нужен синтаксический сахар при проверке noexceptness функции, вы можете использовать вспомогательную функцию, например:

template <typename R, typename... Params>
constexpr bool is_noexcept(R(*p)(Params...)) {
    return noexcept(p(std::declval<Params>()...));
}

И применить таким образом:

void method1() noexcept(is_noexcept(strProcessor)) …

Демо.

person Columbo    schedule 27.07.2015