Как бороться с -Wreturn-типом для переключения на перечисляющий класс C ++ 11? - PullRequest
0 голосов
/ 13 ноября 2018

Если у меня есть функция, которая возвращает значение, основанное на переключении enum class, gcc испускает warning: control reaches end of non-void function [-Wreturn-type].Пример кода:

enum class Test { a, b, c } ;

int foo(Test test) {
    switch (test) {
        case Test::a: return 0;
        case Test::b: return 1;
        case Test::c: return 2;
    }
}

Я думал о двух решениях, но ни одно из них не кажется правильным:

1) имеет случай по умолчанию, который выбрасывает.Однако, когда я добавляю дополнительного члена к enum class, я больше не получаю сообщение об ошибке, пропустившее дело.

2) Подавляю предупреждение с помощью прагмы, но тогда я не защищаюсь от чьей-либо передачив static_cast<Test>(123).

Итак, мой вопрос, как бороться с ошибками типа -Wreturn-типа при переключении на перечисляющий класс C ++ 11?

Ответы [ 2 ]

0 голосов
/ 13 ноября 2018

Примечание: этот ответ написан с учетом производительности (если вам это не нужно, просто проигнорируйте это и добавьте фатальную ошибку после переключения).

Я бы рекомендовал использовать специфическую для компилятора функцию, чтобы пометить недоступный код. Все основные компиляторы имеют что-то вроде этого. Например, GCC / Clang / icc имеет __builtin_unreachable, MSVC имеет __assume(false).

Используйте эти инструменты в режиме выпуска. В режиме отладки поместите туда фатальную ошибку (утверждение, исключение, что угодно). Таким образом, в процессе разработки вы будете ловить ошибки, а в режиме выпуска сгенерированный код будет эффективным.

Обратите внимание, есть предложение , которое намеревается добавить std::unreachable() в C ++. Когда это, надеюсь, пройдет, вы можете использовать его в таких кодах. А до тех пор вы должны прибегать к ранее упомянутому решению для конкретного компилятора.

0 голосов
/ 13 ноября 2018

Обычно я ставлю что-то после переключателя, будь то throw something() или return -1.Вы должны убедиться, что во время выполнения вызов этой функции по крайней мере безопасен, что бы ни происходило.Ваш компилятор говорит вам об этом.

Пример:

enum class Test { a, b, c } ;

int foo(Test test) {
    switch (test) {
        case Test::a: return 0;
        case Test::b: return 1;
        case Test::c: return 2;
    }

    throw std::runtime_error("Unhandled Test enumerator " + std::to_string((int)test) + " in foo()");
}

В идеале ваши клиенты никогда не увидят этого, но, если они это сделают (посредством вашего верхнего уровня catch - выесть, верно?), вы сразу же знаете, в чем проблема, и можете ее исправить.

Дополнительно (но не только) Я рассмотрю вопрос об отладке утверждения типа assert (илипроектный эквивалент), так что эта ошибка обнаружена во время разработки.(Хотя в приведенном выше примере с try это фактически предотвратит создание полезного сообщения об ошибке, поэтому это не всегда уместно.)

Также, если вы включите -Werror, то не сможете добавить элементдо switch, ваш проект не будет построен в любом случае, так что это решает проблему у источника (буквально!).

В общем, не игнорируйте и не пытайтесь подавлять предупреждения: обращайте внимание на них!

...