23

修饰符可以noexcept应用于 lambda 表达式吗?如果是这样,怎么做?

可以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就是always noexcept,这意味着它只有在使用noexcept回调时才可调用。

4

2 回答 2

29

修饰符可以noexcept应用于 lambda 表达式吗?如果是这样,怎么做?

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);
}
于 2013-05-15T17:16:33.637 回答
7

关于第一个问题:

noexcept 修饰符可以应用于 lambda 表达式吗?如果是这样,怎么做?

是的,只需在参数列表后添加异常规范即可:

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

根据 C++11 标准的第 5.1.2/5 段:

lambda 表达式的闭包类型具有公共内联函数调用运算符 (13.5.4),其参数和返回类型分别由 lambda 表达式的参数声明子句和尾随返回类型描述。当且仅当 lambda 表达式的 parameter-declaration-clause 后面没有 mutable 时,此函数调用运算符才声明为 const (9.3.1)。它既不是虚拟的,也不是声明为 volatile 的。默认参数 (8.3.6) 不应在 lambda 声明符的参数声明子句中指定。 在 lambda 表达式上指定的任何异常规范都适用于相应的函数调用运算符. lambda-declarator 中的属性说明符序列属于相应函数调用运算符的类型。[ 注意:在 lambda-declarator 中引用的名称是在 lambda-expression 出现的上下文中查找的。——尾注]

于 2013-05-15T17:16:10.187 回答