使用noexcept作为lambda修饰符或参数约束

Tim*_*lds 16 c++ lambda noexcept c++11

可以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
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

几乎可以通过以下代码完成,但我想知道是否有办法使用类似上面的替代方法.

void f_async(std::function<void (int)> callback)
    noexcept(callback(std::declval<int>()))
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

当然这里的问题是,f_async可能是noexcept(false),如果回调是noexcept(false)-我想要一个更强有力的声明,f_async永远 noexcept,这意味着如果你使用它只是调用noexcept回调函数.

ken*_*ytm 18

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

noexcept括号后添加:

[](Args args) noexcept { ... }
Run Code Online (Sandbox Code Playgroud)

可以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
}
Run Code Online (Sandbox Code Playgroud)

但是,这个方法不能直接在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);
}
Run Code Online (Sandbox Code Playgroud)

  • 很好的尝试,但在clang 3.5中将自由函数传递给f_async时不起作用. (2认同)

And*_*owl 5

关于第一个问题:

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

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

[] (int i) noexcept { return i * 1; };
//         ^^^^^^^^
Run Code Online (Sandbox Code Playgroud)

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

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