Будут ли исключения разумным способом вернуть различные типы? - PullRequest
0 голосов
/ 16 марта 2020

Мне было интересно: поскольку исключения могут быть любого типа, будут ли они жизнеспособными для возврата другого типа в зависимости от условий?

Я знаю, что это не очень понятно, поэтому я приведу пример : для приложения обмена сообщениями мы хотим, чтобы пользователи могли отправлять свои позиции, но из соображений конфиденциальности мы хотим, чтобы оно отображалось только в том случае, если пользователь онлайн:

void getUserPosition(user& u) {
    if(!u.isOnline()) throw false;
    else throw u.getPosition();
}

void sendUserPosition(user& u) {
    try {
        getUserPosition(u);
    } catch(bool e) {
        //send a message like "user isn't online"
    } catch(userPosition e) {
        //send the position
    }
}

Это позволит избежать необходимости для -1 s как сбойные флаги операций и тому подобное. Мысли? Мнения? Я что-то упустил полностью?

Ответы [ 3 ]

2 голосов
/ 16 марта 2020

Исключения следует использовать для исключений, а не для обычных частей условного кода. Если «не в сети» теперь исключение - дело вкуса.

Но если ваш вопрос носит более общий характер и требует возврата различных типов возврата из одной функции, вам следует подумать об использовании std :: вариант . С std :: hold_alternative вы можете спросить , какой тип был сохранен в варианте. Есть несколько способов справиться с содержанием вариантов, например 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...
}
2 голосов
/ 16 марта 2020

Абсолютно нет. Вы не приносите меч на стол, чтобы резать овощи. В данном случае это даже не меч. Это Bru sh.

Шутки, глядя на то, что вы хотите сделать, это означает, что вы уже знаете, какие возможные типы возвращаемого значения. Поскольку это так, используйте std :: variable .

1 голос
/ 16 марта 2020

Пока все исключения, которые вы используете таким образом, являются производными от общего базового класса, например,

struct payload_base_class : public std::exception
{
};

, тогда я вижу, что ваш шаблон может быть полезен. Я предписал эту общность, чтобы вы могли различать guish между вашими return исключениями вкуса и исключениями, которые вы должны обрабатывать более стандартным способом.

(Возможно, вы не захотите std::exception в качестве базового класса, иначе ваши исключения могут быть непреднамеренно перехвачены. Это для вас.)

Этот метод имеет преимущество перед подходом std::variant в том, что вы можете добавлять новые типы return без необходимости изменения шаблона std::variant; выполнение этого может привести к серьезным изменениям.

C ++ разработан, чтобы разрешать такие эксплойты. Тот факт, что люди не имели в виду этот вариант использования при разработке исключений, не делает этот подход незаконным. Шаблон метапрограммирования тоже вырос непреднамеренно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...