Ответ 1
В соответствии с этим (принятым) предложением, поскольку С++ 17; поскольку noexcept является частью типа функции, будет ли код выше печатать
true
?
Да.
Тип f
будет выведен на void(*)() noexcept
, поскольку преобразование функции в указатель, примененное к asdf
, сохранит свойство noexcept
. Вызов указателя функции noexcept
, безусловно, не может генерировать исключение, если только одно из его подвыражений не делает.
Для точной формулировки см. [expr.unary.noexcept]/3 и [expect.spec]/13. Обратите внимание, что новая формулировка в последнем абзаце из проекта С++ 17 исходит из P0012R1, которая связана в OP.
Результатом оператора
noexcept
являетсяtrue
, если набор потенциальных исключений выражения ([except.spec]) пуст, аfalse
в противном случае....
- Если
e
- вызов функции ([expr.call]):
- Если его постфиксное выражение является (возможно, в скобках) id-выражением ([expr.prim.id]), доступом к члену класса ([expr.ref]) или операцией указателя на член ([expr.mptr.oper]), выражение-выражение которого является id-выражением, S - это набор типов в спецификации исключения объекта, выбранного содержащимся в нем идентификатором (после разрешения перегрузки, если применимо)....
Таким образом, набор потенциальных исключений из f()
совпадает с набором типов в спецификации исключения f
, который пуст, поскольку f
объявлен noexcept
.
Перейдем к второму вопросу:
Указание
noexcept
кажется проигнорированным в С++ 14 или 11. Будет ли этот код работать в соответствии с С++ 17?
Кажется, ваш вопрос: будет ли std::function<void() noexcept>
отказаться от функции, которая может генерировать исключения?
Я бы сказал, что он неясен. В настоящей редакции стандарта std::function<void() noexcept>
на самом деле не определен, так как std::function<double(float) const>
не является определены. Это было, конечно, не проблема в С++ 14, так как noexcept
не считался частью типа функции.
Будет ли std::function<void() noexcept>
просто сломаться на С++ 17? Это неуверенно для меня. Давайте взглянем на текущую формулировку, чтобы угадать, каково должно быть поведение.
Стандарт требует, чтобы аргумент конструктору std::function<R(ArgTypes..)>
был "Lvalue-Callable" для типов аргументов ArgTypes...
и возвращаемого типа R
, который означает:
Вызываемый тип ([func.def])
f
является Lvalue-Callable для типов аргументовArgTypes
и возвращает типR
, если выражениеINVOKE(declval<F&>(), declval<ArgTypes>()..., R)
, рассматриваемое как неоцененный операнд (раздел [expr]), хорошо сформирован ([func.require]).
Возможно, должно быть дополнительное требование: если тип функции noexcept
, то noexcept(INVOKE(...))
также должен быть истинным. Тем не менее, эта формулировка отсутствует в нынешнем проекте.
В P0012R1 есть комментарий, который:
Открытая проблема заключается в том, как распространять "noexcept" через
std::function
.
Я предполагаю, что они означают, что неясно, как std::function
может быть реализовано, если это дополнительное требование было наложено. Надеюсь, кто-то еще может предоставить более подробную информацию.