Использование noexcept в качестве лямбда-модификатора или ограничения параметров

Может ли noexcept модификатор применить к лямбда-выражению? Если так, то как?

Можно noexcept сделать ограничение на аргумент функции? Например, что-то вроде в следующем коде, где означает, что функция обратного вызова должна быть noexcept?

//probably not valid code - I'm just trying to express the idea
void f_async(std::function<void (int) noexcept> callback) noexcept
{
...
}

Это может почти это можно сделать с помощью следующего кода, но мне интересно, есть ли способ использовать что-то вроде вышеупомянутой альтернативы.

void f_async(std::function<void (int)> callback)
noexcept(callback(std::declval<int>()))
{
...
}

Проблема здесь, конечно, в том, что f_async может быть noexcept(false) если обратный вызов noexcept(false) — Я хочу сделать более сильное заявление, что f_async является всегда noexceptЭто означает, что он вызывается только если вы используете noexcept Перезвоните.

16

Решение

Может ли noexcept модификатор применить к лямбда-выражению? Если так, то как?

добавлять noexcept после скобок:

[](Args args) noexcept { ... }

Можно noexcept сделать ограничение на аргумент функции?

Да, используйте enable_if:

template <typename F>
auto f_async(const F& func) noexcept
-> typename std::enable_if<noexcept(func(0))>::type {
func(0);
}

int main() {
f_async([](int x) noexcept {});
f_async([](int x) {}); // <- this line won't compile
}

тем не мение, этот метод не может работать напрямую в g ++ 4.7 (он работает в clang ++ 3.2), потому что он не может искажать noexcept выражение еще:

3.cpp: 5: 6: извините, не реализовано: искажение noexcept_expr

Вы можете обойти это, используя структуру оболочки:

template <typename F, typename... Args>
struct EnableIfNoexcept
: std::enable_if<noexcept(std::declval<F>()(std::declval<Args>()...))> {};

template <typename F>
auto f_async(const F& func) noexcept -> typename EnableIfNoexcept<F, int>::type {
func(0);
}
17

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

По первому вопросу:

Может ли модификатор noexcept быть применен к лямбда-выражению? Если так, то как?

Да, просто добавьте спецификацию исключения после списка параметров:

[] (int i) noexcept { return i * 1; };
//         ^^^^^^^^

В соответствии с пунктом 5.1.2 / 5 стандарта C ++ 11:

Тип закрытия для лямбда-выражения имеет открытый оператор вызова встроенной функции (13.5.4), параметры которого
и тип возврата описываются параметром-объявлением-лямбда-выражения и трейлинг-возвращением
тип соответственно. Этот оператор вызова функции объявляется const (9.3.1) тогда и только тогда, когда лямбда-выражение
Параметр-объявление-предложение не сопровождается изменяемым. Он не является ни виртуальным, ни объявленным
неустойчивый. Аргументы по умолчанию (8.3.6) не должны указываться в условии объявления параметров лямбда-декларатора.
Любая спецификация исключения, указанная в лямбда-выражении, применяется к соответствующей функции
оператор вызова
. Атрибут-спецификатор-seq в лямбда-деклараторе относится к типу соответствующего
оператор вызова функции. [Примечание: имена, на которые ссылается лямбда-декларатор, ищутся в контексте
который появляется лямбда-выражение. —Конечная записка]

4

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