如何在查找函数 returns 引用时编写干净的 try/catch 块?
how to write clean try/catch block when find function returns a reference?
我有一些代码如下所示:
const SomeType & elt = x.find();
try {
// ... do something with elt ...
} catch (...) {
// handle processing exception
}
它有效,但由于环境不断变化,现在 find()
方法可能会抛出“未找到”异常,我需要捕获该异常。
我想写的是
try {
const SomeType & elt = x.find();
} catch (...) {
// handle "not found" exception
return;
}
try {
// ... do something with elt ...
} catch (...) {
// handle processing exception
}
但这当然行不通,因为在到达其处理块时,elt
已不在范围内。我无法将其重新排列为
const SomeType & elt;
try {
elt = x.find();
} catch (...) {
// handle "not found" exception
return;
}
因为 C++ 中的引用类型当然不允许未初始化。所以我剩下的选择是暂时将 elt
设置为对类型 SomeType
的虚拟对象的引用,我不想这样做,或者嵌套 try/catch 块,像这样:
try {
const SomeType & elt = x.find();
try {
// ... do something with elt ...
} catch (...) {
// handle processing exception
}
} catch (...) {
// handle "not found" exception
}
我也不喜欢这样:嵌套令人困惑,而且我不喜欢“未找到”异常处理程序最后隐藏在那里的方式。
谁能想出更好的安排方式? (当然,在 C 中,我们只是让 find
函数 return 在未找到的情况下有一个空指针,并以这种方式处理它,但我想尽量不要成为一个旧的当我写 C++ 时是 C 程序员,无论如何 x.find()
已经设置为 return 一个引用,而不是一个指针。)
拆分成另一个函数:
void func1()
{
try {
const SomeType & elt = x.find();
func2(elt);
} catch (...) {
// handle "not found" exception
}
}
void funct2(const SomeType & elt)
{
try {
// ... do something with elt ...
} catch (...) {
// handle processing exception
}
}
尽管总的来说我发现您的界面有点令人不安,因为首先需要所有这些 try/catch 块。不幸的是,很难用如此少的信息就如何改进总体风格提供建议。
它不会合每个人的口味(顺便说一下,行为 是 定义的),但您可以使用
#include <functional>
std::reference_wrapper<const SomeType> elt = elt;
try {
elt = x.find();
} catch (...) {
// handle "not found" exception
return;
}
可以说 elt
的设置本身是对 std::reference_wrapper
的滥用,它的默认构造函数和移动构造函数被设计删除:我正在规避它。
本质上 std::refernce_wrapper
是一个隐藏在引擎盖下的指针,但您可以重新绑定它,这基本上就是您想要在此处执行的操作。
如果异常不同,您可以使用相同的 try 块:
try {
const SomeType& elt = x.find();
// ... do something with elt ...
} catch (const NotFoundException&) {
// handle "not found" exception
} catch (...) {
// handle processing exception
}
else rebinding reference 是不允许的,但是一般可以用指针或者std::reference_wrapper
来模拟,
和可选引用(std 中不允许,但 boost 允许)可能由指针或 std::optional<std::reference_wrapper<T>>
.
模拟
所以:
const SomeType* eltPtr = nullptr;
try {
eltPtr = &x.find();
} catch (const NotFoundException&) {
// handle "not found" exception
return;
}
const SomeType& elt = *eltPtr;
try {
// ... do something with elt ...
} catch (...) {
// handle processing exception
}
我有一些代码如下所示:
const SomeType & elt = x.find();
try {
// ... do something with elt ...
} catch (...) {
// handle processing exception
}
它有效,但由于环境不断变化,现在 find()
方法可能会抛出“未找到”异常,我需要捕获该异常。
我想写的是
try {
const SomeType & elt = x.find();
} catch (...) {
// handle "not found" exception
return;
}
try {
// ... do something with elt ...
} catch (...) {
// handle processing exception
}
但这当然行不通,因为在到达其处理块时,elt
已不在范围内。我无法将其重新排列为
const SomeType & elt;
try {
elt = x.find();
} catch (...) {
// handle "not found" exception
return;
}
因为 C++ 中的引用类型当然不允许未初始化。所以我剩下的选择是暂时将 elt
设置为对类型 SomeType
的虚拟对象的引用,我不想这样做,或者嵌套 try/catch 块,像这样:
try {
const SomeType & elt = x.find();
try {
// ... do something with elt ...
} catch (...) {
// handle processing exception
}
} catch (...) {
// handle "not found" exception
}
我也不喜欢这样:嵌套令人困惑,而且我不喜欢“未找到”异常处理程序最后隐藏在那里的方式。
谁能想出更好的安排方式? (当然,在 C 中,我们只是让 find
函数 return 在未找到的情况下有一个空指针,并以这种方式处理它,但我想尽量不要成为一个旧的当我写 C++ 时是 C 程序员,无论如何 x.find()
已经设置为 return 一个引用,而不是一个指针。)
拆分成另一个函数:
void func1()
{
try {
const SomeType & elt = x.find();
func2(elt);
} catch (...) {
// handle "not found" exception
}
}
void funct2(const SomeType & elt)
{
try {
// ... do something with elt ...
} catch (...) {
// handle processing exception
}
}
尽管总的来说我发现您的界面有点令人不安,因为首先需要所有这些 try/catch 块。不幸的是,很难用如此少的信息就如何改进总体风格提供建议。
它不会合每个人的口味(顺便说一下,行为 是 定义的),但您可以使用
#include <functional>
std::reference_wrapper<const SomeType> elt = elt;
try {
elt = x.find();
} catch (...) {
// handle "not found" exception
return;
}
可以说 elt
的设置本身是对 std::reference_wrapper
的滥用,它的默认构造函数和移动构造函数被设计删除:我正在规避它。
本质上 std::refernce_wrapper
是一个隐藏在引擎盖下的指针,但您可以重新绑定它,这基本上就是您想要在此处执行的操作。
如果异常不同,您可以使用相同的 try 块:
try {
const SomeType& elt = x.find();
// ... do something with elt ...
} catch (const NotFoundException&) {
// handle "not found" exception
} catch (...) {
// handle processing exception
}
else rebinding reference 是不允许的,但是一般可以用指针或者std::reference_wrapper
来模拟,
和可选引用(std 中不允许,但 boost 允许)可能由指针或 std::optional<std::reference_wrapper<T>>
.
所以:
const SomeType* eltPtr = nullptr;
try {
eltPtr = &x.find();
} catch (const NotFoundException&) {
// handle "not found" exception
return;
}
const SomeType& elt = *eltPtr;
try {
// ... do something with elt ...
} catch (...) {
// handle processing exception
}