尝试/捕获参考分配
try/catch around reference assignment
我想从返回引用的方法中捕获异常,而不会从使用该引用的后续调用中捕获相同的异常。例如:
try {
Something &o = myMap.at(myIndex);
foo(o);
} catch(std::out_of_range &e) {
// If this was thrown by myMap.at, we can handle it
// If this was thrown by foo, we can't, and need to propagate it
}
所以我想做这样的事情:
Something &o;
try {
o = myMap.at(myIndex);
} catch(std::out_of_range &e) {
// Handle the error
}
foo(o);
但是,当然,这是无效的。我可以想办法将foo
的异常包装在另一个异常中,然后将其解开到try
之外,但这相当混乱。有没有更好的方法?
MCVE可以在这里找到:https://ideone.com/DJHxpO
您可以使用立即调用的 lambda 表达式:
Something &o = [&]() -> decltype(auto) {
try {
return myMap.at(myIndex);
} catch(std::out_of_range &e) {
// Handle the error
// Return some other object for o to refer to.
}
}();
foo(o);
您可以改用指针:
Something *o; // initialize it with nullptr if necessary
try {
o = &myMap.at(myIndex);
} catch(std::out_of_range &e) {
// Handle the error
}
foo(*o); // check whether it's nullptr before dereference if necessary
我认为这是boost::optional
的一个很好的用例(std::在c ++ 17中(。
您实际上并不想生成或处理异常,因为不在地图中的项目不是例外情况。
我想我会这样表达:
int myIndex = 1;
foo(maybe_at(myMap, myIndex).value_or_eval([]()->Something& {
// perform error code here
return default_something;
}));
完整的代码示例如下:
#include <map>
#include <type_traits>
#include <boost/optional.hpp>
template<class Container>
struct container_traits
{
using maybe_const_type = std::remove_reference_t<Container>;
using container_type = std::decay_t<Container>;
using is_const = std::is_const<maybe_const_type>;
using key_type = typename container_type::key_type;
using raw_mapped_type = typename container_type::mapped_type;
using mapped_type = std::conditional_t<is_const::value, std::add_const_t<raw_mapped_type>, raw_mapped_type>;
using mapped_reference = std::add_lvalue_reference_t<mapped_type >;
};
template<class Container, class Key>
auto maybe_at(Container&& container, Key&& key)
{
using traits = container_traits<Container>;
using result_type = boost::optional<typename traits::mapped_reference>;
auto result = result_type {};
auto ifind = container.find(key);
if (ifind != container.end()) {
result = ifind->second;
}
return result;
}
struct Something {};
void foo(Something&) {}
void foo(const Something&) {}
std::map<int, Something> myMap1;
const std::map<int, Something> myMap2;
auto default_something = Something{};
int main() {
int myIndex = 1;
foo(maybe_at(myMap1, myIndex).value_or_eval([]()->Something& {
// perform error code here
return default_something;
}));
foo(maybe_at(myMap2, myIndex).value_or_eval([]()->Something const& {
// perform error code here
return default_something;
}));
}
适用于所有版本的C++的简单方法是
bool mapped = false;
try {
Something &o = myMap.at(myIndex);
mapped = true;
foo(o);
} catch(std::out_of_range &e) {
if (mapped) throw;
// if we get to here, the exception was thrown by myMap.at()
}
这也避免了在引用失败时使引用引用myMap.at()
的需要。
相关文章:
- 将数组的地址分配给变量并删除
- vector.resize()中的分配错误
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 如何将向量分配给参考变量?
- 为什么即使传递给函数作为参考,指针也未被分配
- 为什么合成的复制分配运算符被定义为如果类有参考成员,则将其定义为删除
- 尝试/捕获参考分配
- 重新分配到const参考
- 分配从方法返回到变量的参考
- 分配运算符过载:返回void与返回参考参数
- 试图分配输出以查看指针和参考输出时,请勿命名类型错误
- 如何通过QT中的参考为qobject进行分配
- 分配给返回参考的函数
- C 复制分配运算符,用于参考对象变量
- C 通过参考分配 /数组传递内存
- 如何禁止分配不参考变量
- 通过参考数组传递分配的堆栈参数
- 参考记忆分配技术
- 为什么我们在分配运算符过载中使用参考返回,而不是在加上Minus OPS中使用
- 参考抽象类分配问题