最好的方法是什么:
for (const auto &arg : args) {
try {
auto var = create(arg);
} catch (const std::invalid_argument &e) {
continue;
}
// ...
// use(var)
// ...
}
一种方法是移动
// ...
// use(var)
// ...
进入try块,但这会引入整个嵌套负载。 另外,我不想从use
中捕获错误
TypeOf(var)
是一个没有默认构造函数的类。
一种方法是将use(var)
移到try块中,但这会引入大量嵌套
您可以将use(var)
移到单独的函数中,并在try
块中调用该函数:
void use(var_type& var) {
//...
}
for (const auto &arg : args) {
try {
auto var = create(arg);
use(var);
} catch (const std::invalid_argument &e) {
continue;
}
}
由于您无法控制create
或use
块,并且希望确保不捕获在use
块中抛出的任何内容,因此可以将create
异常作为不同类型重新抛出,以仅捕获该异常。 由于异常应该只发生在异常情况下,因此这种开销应该不是任何问题。
示例:
struct create_error : std::invalid_argument {
using std::invalid_argument::invalid_argument;
};
Foo create(const char* arg) {
return {arg};
}
Foo create_wrapper(const char* arg) {
try {
create(arg);
}
catch(const std::invalid_argument& ex) {
throw create_error(static_cast<const create_error&>(ex));
}
}
void use(Foo& f) {
// may throw std::invalid_argument, but it won't be caught below
}
for (const auto& arg : args)
{
try {
auto var = create_wrapper(arg);
use(var);
}
catch (const create_error& e) {
continue;
}
}
也许std::optional
才是您需要的。 您可以将它与没有默认构造函数的类一起使用,如下所示
如果您不想知道抛出异常的值是什么,可以使用如下所示的方法
#include <iostream>
#include <optional>
struct A{
int var;
explicit A(int arg):var{arg}{}
A() = delete ;
};
A create( int arg){
if (arg == 5 || arg == 8)
throw std::invalid_argument{""};
return A{arg};
}
void use(const A & a)
{
std::cout << "\n" << a.var;
}
int main()
{
std::optional<A> a;
for (size_t i{}; i < 10; ++i) {
try {
a = create(i);
} catch (const std::invalid_argument &e) {
continue;
}
if(a) use(a.value());
}
}
活着
我认为它主要取决于变量类型。
例如,如果它是一个指针(smart或dumb),您可以将它设置为try块之前的nullptr
,并检查它是否被分配在try块之外。
如果它是另一种类型,无法获取nullptr
,则可以使用默认值(如果可能的话)。 如果这是不可能的,那么,你应该给出一个具体的例子,也许你可以得到一个更好的答案。