lenerdv
lenerdv

Reputation: 197

would exceptions be a reasonable way to return different types?

I've been wondering: since exceptions can be of any type, would they be viable for returning a different type depending on the conditions?

I know it's not very clear so I'll make an example: for a messaging app, we want the users to be able to send their position, but for privacy reasons, we want it to only be shown if the user is online:

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
    }
}

This would avoid the need for -1s as failed operation flags and stuff like that. Thoughts? Opinions? Am I completely missing something?

Upvotes: 0

Views: 90

Answers (3)

Bathsheba
Bathsheba

Reputation: 234715

So long as all the exceptions you use in this way are derived from a common base class, e.g.

struct payload_base_class : public std::exception
{
};

then I can see that this pattern of yours could be useful. I've mandated this commonality so you can distinguish between your return-flavour exceptions over ones that you should treat in a more standard fashion.

(It's possible that you might not want std::exception as the base class, else your exceptions might be caught unintentionally. That's for you to study.)

This technique has an advantage over a std::variant approach in that you can add new return types without having to change the std::variant template; doing that latter can introduce breaking changes.

C++ is designed to allow such exploits. Just because folk didn't have this use-case in mind when exceptions were developed doesn't make this approach illegitimate. Template metaprogamming grew up unintentionaly too.

Upvotes: 1

Klaus
Klaus

Reputation: 25613

Exceptions should be used for exceptions and not for normal conditional code parts. If "not online" is now an exception is matter of taste.

But if your question is more general and asks about giving back different return types from a single function you should think of using 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...
}

Upvotes: 2

theWiseBro
theWiseBro

Reputation: 1529

Absolutely not. You don't bring a sword to the table to cut vegetables. In this case, its not even a sword. Its a brush.

Jokes apart, looking at what you want to do, this means you already know what possible types of the return value are. Since that's the case, use std::variant.

Upvotes: 2

Related Questions