c++ - 在现代 C++ 中使用 try..catch block 通过模板元编程包装任意函数调用

标签 c++ templates c++11 lambda c++14

我想创建一些模板,基本上应该包装它的参数。参数应该是一个任意的函数调用,它通过一些带有前缀和后缀代码的模板元编程魔法被包装。

我想像下面这样使用它:

auto result = try_call( some_vector.at(13) );

try_call 将以某种方式定义,它将 try..catch block 包装在 some_vector.at(13) 周围。像这样:

template<typename T>
// some template metaprogramming magic here
try {
    auto value = // execute the parameter here, i.e. some_vector.at(13);
    return std::experimental::optional<T>(value);
} 
catch (std::exception&) {
    return std::experimental::nullopt;
}

有 Bjarne Stroustrup 的那篇论文,但这并没有完全描述我需要的东西,而且我找不到解决这个问题的方法。

如果这不能直接实现,我目前正在考虑通过采用 lambda 的模板函数来实现:

template<typename Func>
auto try_call(Func f) {
    try {
        return f();
    } catch(std::exception&) {
        return std::experimental::nullopt;
    }
}

但我不知道这是否是个好主意。我猜 lambda 有一些开销?我想避免任何不必要的开销。

最佳答案

实际上,您使用 lambda 的解决方案非常好且高效。从类型理论的角度来看,try_call 是一个高阶函数:它将另一个函数作为参数并在 try catch 上下文中执行它。

template<typename Func>
auto try_call(Func f) -> std::experimental::optional<std::decay_t<decltype(f())>> {
    try {
        return std::experimental::make_optional(f());
    } catch(std::exception&) {
        return std::experimental::nullopt;
    }
}

用 lambda 调用它会产生你想要的结果而没有任何开销。 lambda 被编译为具有重载函数调用运算符的匿名结构。此结构用作 try_call 函数的模板参数。因此,编译器在调用 f() 时确切地知道要执行的函数,并且它将被内联。不涉及任何开销。

关于c++ - 在现代 C++ 中使用 try..catch block 通过模板元编程包装任意函数调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31526796/

相关文章:

c++ - 让 GDB 显示模板参数的类型

c++ - 删除原子/防护数据中的数据

c++ - 将 packaged_task 移动到 lambda

c++ - 对 cv::Mat::Mat() 的 undefined reference

c++ - 小字符串优化(调试与 Release模式)

c++ - 如何使用命名空间中单独 header 中定义的类

c++ - 生成IDE工程文件

javascript - 使用刷过的 HTML 模板

c++ - Lambda 成员函数

c++ - 如何检查模板模板类的接口(interface)