Как функция [[noreturn]] может иметь тип возвращаемого значения?

Я столкнулся с этим «прекрасным» примером «хорошо читаемого» и «элегантного» кода, но у меня возникли проблемы с его пониманием:

struct S {

[[noreturn]] virtual inline auto f(const unsigned long int *const)
–> void const noexcept;
};

Вот что я понимаю (пожалуйста, поправьте меня, если я ошибаюсь):

  • f() является функцией-членом S
  • virtual — может быть переопределено производными классами
  • inline — компилятор должен попытаться генерировать код для звонка в f вместо того, чтобы называть это нормально
  • const — функция не может изменить любой из Sучастники
  • noexcept — функция никогда не сгенерирует (не может сгенерировать или не сгенерировать)
  • параметр: const указатель на const unsigned long int
  • auto .... -> void — суффикс возвращаемого типа void
  • [[noreturn]] — это никогда returns

Вот мои основные проблемы:

  • Если функция объявлена ​​как [[noreturn]], Это никогда возвращается к своему абоненту; так как он может иметь тип возвращаемого значения void? Каков смысл возвращаемого типа в этой функции?
  • Будет ли этот код компилироваться с int вместо void например?
  • Что будет практического использования для такой функции? Бросить исключение?
  • Куда идет поток кода после завершения выполнения этой функции (после } )?

Я не смог заставить этот код работать в VS2013 Preview, поэтому я полагаю, что эти функции еще не реализованы.

Мне очень любопытно, поэтому я буду признателен, если кто-нибудь сможет объяснить! ура

9

Решение

[[noreturn]] это атрибут, который имеет любую семантику. Однако не меняется способ объявления функции: все нормальные функции в C ++ (то есть все функции, кроме конструкторов, деструкторов и операторов преобразования) имеют объявленный тип возврата. Добавление любого атрибута не меняет это правило.

Цель [[noreturn]] Атрибут, вероятно, указывает на то, что функция никогда не возвращается нормальным способом. Учитывая, что функция также объявлена noexcept это в основном означает, что соответствующая функция также не может вызвать исключение. Одним из примеров функции с похожим поведением является exit() который завершает программу. Я мог предположить, что функции, реализующие некоторый цикл приложения, также могли бы быть квалифицированы. В любом случае, [[noreturn]] сообщает системе, что соответствующая функция никогда не вернется, т. е. падение функции («после»), вероятно, приведет к неопределенному поведению.

19

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

Если функция объявлена ​​как [[noreturn]], она никогда не возвращается к своему вызывающему; так как он может иметь возвращаемый тип void? Каков смысл возвращаемого типа в этой функции?

От этот Q&A вы можете видеть, что noreturn — это способ сообщить компилятору, что функция не возвращает. Обычно это означает, что он либо имеет бесконечный цикл (часто встречающийся на серверах, которые должны работать бесконечно), либо вызывает exit(), terminate() и тому подобное, выход из приложения без возврата к основному.
[[noreturn]] не является обязательным, то есть вы не иметь указать это. Это атрибут, то есть основной синтаксис определения / объявления функции остается неизменным, поэтому функция имеет иметь тип возвращаемого значения, как и любая другая функция.

Будет ли этот код компилироваться с int вместо void, например?

Да, это так, хотя компилятор может предупредить вас, что не имеет смысла возвращать что-то из функции, которая никогда не вернется.

Что будет практического использования для такой функции? Бросить исключение?

Первое, что приходит на ум, — это какой-то бесконечный цикл, например, обработка входящих запросов на сервере. Бросать исключение можно [[noreturn]] функции, но это не совсем вариант, потому что он явно говорит noexcept, Бросок вызовет вызов std::terminate(), что приводит к самому завершению программы, но прежде к определенному для реализации количеству разматывания стека, что фактически означает [[noreturn]] все равно будет применимо.

Куда идет поток кода после завершения выполнения этой функции (после})?

Функция никогда не достигает своего закрытия }, Он либо работает бесконечно (до тех пор, пока кто-то не потянет за штекер), либо он выходит из строя ненормально, то есть по завершению программы. Другими словами, если функция больше не выполняется, она на самом деле не завершена, но прервана выполнение, и нет программы и потока управления для перехода.

6

Другие ответы великолепны, но я собираюсь представить альтернативный ответ для

Если функция объявлена ​​как [[noreturn]]никогда не возвращается к своему вызывающему; так как он может иметь возвращаемый тип void? Каков смысл возвращаемого типа в этой функции?

Одна из причин, по которой вам может понадобиться тип возвращаемого значения (и, в этом случае, возвращаемый тип, отличный от void), заключается в том, что функция переопределяет метод суперклассов.

struct Parent {
virtual int f()=0;
}

struct Child {
[[noreturn]] override int f() noexcept { ... }
};

В некоторых случаях компилятор сможет использовать [[noreturn]] производить лучший код. Но в других ситуациях f может быть назван полиморфно, и, следовательно, должен соответствовать подписи своих родителей.

2
По вопросам рекламы [email protected]