例外是 return 不同类型的合理方式吗?
would exceptions be a reasonable way to return different types?
我一直在想:既然异常可以是任何类型,那么它们是否可以根据条件返回不同的类型?
我知道这不是很清楚,所以我举个例子:对于一个消息传递应用程序,我们希望用户能够发送他们的位置,但出于隐私原因,我们希望它只在用户在线:
void get_user_position(User& u) {
if(!u.is_online()) throw false;
else throw u.get_position();
}
void send_user_position(User& u) {
try {
get_user_position(u);
} catch(bool e) {
//send a message like "user isn't online"
} catch(user_position e) {
//send the position
}
}
这将避免需要 -1
s 作为失败的操作标志和类似的东西。想法?意见?我完全错过了什么吗?
绝对不是。你不会带剑到 table 去砍蔬菜 table。在这种情况下,它甚至不是剑。它是一把刷子。
开个玩笑,看看你想做什么,这意味着你已经知道 return 值的可能类型。既然如此,就用std::variant。
Exceptions 应该用于异常而不是用于正常的条件代码部分。如果 "not online" 现在是一个例外是品味问题。
但是,如果您的问题更笼统,并且询问有关从单个函数返回不同 return 类型的问题,您应该考虑使用 std::variant. With std::holds_alternative you can ask which type was stored in the variant. There are several methods to deal with the content of variants e.g. std::visit
struct A{};
struct B{};
std::variant < A,B > Func( int x)
{
if ( x == 0 ) return A{};
return B{};
}
int main()
{
auto v = Func( 0 );
if ( std::holds_alternative<A>(v) )
{
std::cout << "A" << std::endl;
}
else if ( std::holds_alternative<B>(v) )
{
std::cout << "B" << std::endl;
}
// or even use std::visit or whatever is helpful...
}
只要您以这种方式使用的所有异常都来自一个公共基础class,例如
struct payload_base_class : public std::exception
{
};
那我就知道你的这个模式会有用了。我已经规定了这种共性,因此您可以区分您的 return
-flavor 异常和您应该以更标准的方式处理的异常。
(有可能你不希望std::exception
作为基础class,否则你的异常可能会被无意中捕捉到,供你学习。)
此技术优于 std::variant
方法,因为您可以添加新的 return
类型而无需更改 std::variant
模板;后者会带来重大变化。
C++ 旨在允许此类攻击。仅仅因为人们在开发异常时没有考虑到这个用例,并不能使这种方法不合法。模板元编程也在无意中成长起来。
我一直在想:既然异常可以是任何类型,那么它们是否可以根据条件返回不同的类型?
我知道这不是很清楚,所以我举个例子:对于一个消息传递应用程序,我们希望用户能够发送他们的位置,但出于隐私原因,我们希望它只在用户在线:
void get_user_position(User& u) {
if(!u.is_online()) throw false;
else throw u.get_position();
}
void send_user_position(User& u) {
try {
get_user_position(u);
} catch(bool e) {
//send a message like "user isn't online"
} catch(user_position e) {
//send the position
}
}
这将避免需要 -1
s 作为失败的操作标志和类似的东西。想法?意见?我完全错过了什么吗?
绝对不是。你不会带剑到 table 去砍蔬菜 table。在这种情况下,它甚至不是剑。它是一把刷子。
开个玩笑,看看你想做什么,这意味着你已经知道 return 值的可能类型。既然如此,就用std::variant。
Exceptions 应该用于异常而不是用于正常的条件代码部分。如果 "not online" 现在是一个例外是品味问题。
但是,如果您的问题更笼统,并且询问有关从单个函数返回不同 return 类型的问题,您应该考虑使用 std::variant. With std::holds_alternative you can ask which type was stored in the variant. There are several methods to deal with the content of variants e.g. std::visit
struct A{};
struct B{};
std::variant < A,B > Func( int x)
{
if ( x == 0 ) return A{};
return B{};
}
int main()
{
auto v = Func( 0 );
if ( std::holds_alternative<A>(v) )
{
std::cout << "A" << std::endl;
}
else if ( std::holds_alternative<B>(v) )
{
std::cout << "B" << std::endl;
}
// or even use std::visit or whatever is helpful...
}
只要您以这种方式使用的所有异常都来自一个公共基础class,例如
struct payload_base_class : public std::exception
{
};
那我就知道你的这个模式会有用了。我已经规定了这种共性,因此您可以区分您的 return
-flavor 异常和您应该以更标准的方式处理的异常。
(有可能你不希望std::exception
作为基础class,否则你的异常可能会被无意中捕捉到,供你学习。)
此技术优于 std::variant
方法,因为您可以添加新的 return
类型而无需更改 std::variant
模板;后者会带来重大变化。
C++ 旨在允许此类攻击。仅仅因为人们在开发异常时没有考虑到这个用例,并不能使这种方法不合法。模板元编程也在无意中成长起来。