Как указать компилятору, что функция всегда выбрасывает? - PullRequest
8 голосов
/ 28 июня 2009

При вызове функций, которые всегда выдают из функции, возвращающей значение, компилятор часто предупреждает, что не все пути управления возвращают значение. Законно так.

void AlwaysThrows() { throw "something"; }

bool foo()
{
    if (cond)
        AlwaysThrows();
    else
        return true; // Warning C4715 here
}

Есть ли способ сообщить компилятору, что AlwaysThrows делает то, что говорит?

Я знаю, что могу добавить еще throw после вызова функции:

{ AlwaysThrows(); throw "dummy"; }

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

Ответы [ 5 ]

16 голосов
/ 08 февраля 2012

Используйте атрибут Noreturn . Это указано в разделе «7.6.3 Атрибут Noreturn [dcl.attr.noreturn]» последней версии стандарта C ++, третье издание ISO / IEC 14882: 2011.

Пример из стандарта:

[[ noreturn ]] void f()
{
    throw "error";
}
6 голосов
/ 28 июня 2009

Вы можете добавить фиктивный оператор возврата после вызова AlwaysThrows () с комментарием, объясняющим, почему он там есть. Это также полезно, когда вызываемая функция всегда выполняет exit () или abort ().

6 голосов
/ 28 июня 2009

Конечно, один вопрос - зачем вам писать такой код? Очевидный ответ на этот вопрос заключается в том, что AlwaysTrows () на самом деле является функцией сообщения об ошибках некоторого вида. В моем собственном коде я фактически использую макрос для создания отчетов об ошибках, потому что он позволяет мне выполнять форматирование строк и получать макросы standatd __LINE__ и __FILE__. Макрос выглядит примерно так:

#define ATHROW( msg )                                               \
{                                                                   \
    std::ostringstream os_;                                         \
    os_ << msg;                                                     \
    throw ALib::Exception( os_.str(), __LINE__, __FILE__ );         \
}

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

int f() int val ) {
   if ( val >= BADVALUE ) {
       ATHROW( "Invalid value " << val << " for val" );
   }
   else {
       return val / 3;
   }
}

тогда я не получу предупреждение о том, что f () не возвращает значение.

4 голосов
/ 28 июня 2009

В Visual C ++ вы можете использовать __declspec (noreturn).

1 голос
/ 14 сентября 2009

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

  1. В нескольких блоках перехвата есть несколько общих строк кода, которые я хотел бы реорганизовать
  2. Все вышеупомянутые блоки улова в конечном итоге отбрасывают исключение.

Несмотря на то, что вы можете поставить фиктивный возврат после метода «всегда бросать», это, вероятно, нарушит OCD вашего Программиста.

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

Exception HandleException() 
{ 
    // Do stuff, like some logging maybe
    return SomeException("something"); 
}

bool foo()
{    
   if (cond)        
       throw HandleException();    
   else        
       return true; // no more warning
}

Таким образом, вам не нужно добавлять лишние строки кода.

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