странный warning
От: -MyXa- Россия  
Дата: 11.11.09 17:13
Оценка:
Привет!

template<typename T>
T const & at(T const * const a, std::size_t const index, std::size_t const size)
{
    return ((index < size) ? a[index] : throw index);
}

int val = at((int const * )0, 1, 0);


Три компилятора говорят, примерно, так: Warning: returning address of local variable or temporary

Почему?
Если не поможет, будем действовать током... 600 Вольт (C)
Re: странный warning
От: Tilir Россия http://tilir.livejournal.com
Дата: 11.11.09 17:24
Оценка: +1
Здравствуйте, -MyXa-, Вы писали:

MX>Три компилятора говорят, примерно, так: Warning: returning address of local variable or temporary


MX>Почему?


Дело в том, что throw попадает под return. Вот так ворнинга уже нет:

template<typename T>
T const & at(T const * const a, std::size_t const index, std::size_t const size)
{
    if (index < size) 
      return a[index];
    throw index;
}


Забавный кстати случай поскольку throw index имеет вообще-то тип void. И почему компилятор вообще разрешает return condition ? int : void -- загадка.
Re[2]: странный warning
От: -MyXa- Россия  
Дата: 11.11.09 19:39
Оценка: 1 (1)
Здравствуйте, Tilir, Вы писали:

T>Дело в том, что throw попадает под return.


Неа. Warning пропадает, если возвращать значение (не ссылку).

T>Забавный кстати случай поскольку throw index имеет вообще-то тип void. И почему компилятор вообще разрешает return condition ? int : void -- загадка.


Ага! Вот из стандарта:

5.16.2 If either the second or the third operand has type (possibly cv-qualified) void, then the lvalue-to-rvalue, array-to-pointer, and function-to-pointer standard conversions are performed on the second and third operands, and one of the following shall hold:

— The second or the third operand (but not both) is a throw-expression; the result is of the type of the other and is an rvalue.

И зачем так сделали? Или это не относится к моему вопросу?
Если не поможет, будем действовать током... 600 Вольт (C)
Re[3]: странный warning
От: Николай Ивченков  
Дата: 11.11.09 20:18
Оценка:
-MyXa-:

MX>5.16.2 If either the second or the third operand has type (possibly cv-qualified) void, then the lvalue-to-rvalue, array-to-pointer, and function-to-pointer standard conversions are performed on the second and third operands, and one of the following shall hold:


MX>— The second or the third operand (but not both) is a throw-expression; the result is of the type of the other and is an rvalue.


MX>И зачем так сделали?


Я бы тоже хотел узнать ответ на этот вопрос В стандарте даже не сказано, каким образом должно получаться это rvalue (возможные варианты: это может быть либо гарантированно исходный объект, либо copy-initialized temporary object, либо copy constructed temporary object).

MX>Или это не относится к моему вопросу?


Относится. Компилятор считает, что ты пытаешься вернуть по ссылке временный объект, который по выходе из функции существовать не будет.
Re: странный warning
От: Erop Россия  
Дата: 11.11.09 22:52
Оценка: 3 (1)
Здравствуйте, -MyXa-, Вы писали:

Почему сказали, но не понятно, зачем писать так кудряво-то?
Кстати, ничто не мешает формально возвращать что-нибудь валидное...

template<typename T>
T const & at(T const * const a, std::size_t const index, std::size_t const size)
{
    return ((index < size) ? a[index] : (throw index), a[0] );
}
Даёт предупреждение?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: странный warning
От: Кодт Россия  
Дата: 11.11.09 23:24
Оценка: +1 :)
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, -MyXa-, Вы писали:


E>Почему сказали, но не понятно, зачем писать так кудряво-то?


А сам что сделал? Теперь к тернарному оператору ещё и запятая прибавилась, и фиктивное обращение к элементу тож...
ИМХО лучше отделить бросок от возврата
template<typename T>
T const & at(T const * const a, std::size_t const index, std::size_t const size)
{
  if(index<0||index>=count)
    throw std::range_error( MAKE_ERROR_MESSAGE("index %d out of range [0,%d)", index,count) );
  return a[index];
}

И кстати! Бросаться целыми числами — дурной тон.
Хотя бы потому, что при catch нас ждут сюрпризы с совпадением-несовпадением формального типа.
Перекуём баги на фичи!
Re[3]: странный warning
От: Erop Россия  
Дата: 12.11.09 06:29
Оценка:
Здравствуйте, Кодт, Вы писали:

E>>Почему сказали, но не понятно, зачем писать так кудряво-то?


К>А сам что сделал? Теперь к тернарному оператору ещё и запятая прибавилась, и фиктивное обращение к элементу тож...

Дык это если таки хочется кудряво
Кудряво-то тоже можно. Просто не нужно...

К>ИМХО лучше отделить бросок от возврата

Конечно лучше.

К>И кстати! Бросаться целыми числами — дурной тон.

К>Хотя бы потому, что при catch нас ждут сюрпризы с совпадением-несовпадением формального типа.

Ну это отдельный вопрос. Кстати, а разве с целыми именно ждут сюрпризы? Хотя при бросании всяких разных типов надо помнить, что преобразования там таки почти не делаются...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: странный warning
От: Кодт Россия  
Дата: 12.11.09 11:23
Оценка: 2 (1) +3
Здравствуйте, Erop, Вы писали:

К>>И кстати! Бросаться целыми числами — дурной тон.

К>>Хотя бы потому, что при catch нас ждут сюрпризы с совпадением-несовпадением формального типа.

E>Ну это отдельный вопрос. Кстати, а разве с целыми именно ждут сюрпризы? Хотя при бросании всяких разных типов надо помнить, что преобразования там таки почти не делаются...


Вообще, неподконтрольное множество используемых типов исключений — это бардак. Но с числами это особенно больно и обидно.

Для классов действует сопоставление с супертипом = базовым классом, что логично.
А для чисел нет супертипа, хотя это и не интуитивно. При выборе сигнатуры функции компилятор делает неявное преобразование (потому что компилятор умный!), а при выборе сигнатуры catch — не делает (потому что это уже не компилятор, а глупый рантайм).

В результате, бросая size_t, нужно ловить именно size_t, а не unsigned long или unsigned int.
Это даёт возможности для ряда ошибок:
— случайный перехват (например, одна функция кидает index, а другая — hresult; если тип индекса совпадёт с HRESULT, будет внезапно)
— случайное игнорирование (например, все функции кидают index, но у большинства это int, а у нескольких пуристов size_t и ptrdiff_t)
— случайный бросок неподходящего типа (например, все кидают char, но в одном месте было throw('Z'), а в другом — throw('A'+25), продвинутый до int)

Ну и для рефакторинга это мучительно. В специально обученный тип исключения всегда можно подверстать дополнительную информацию, да и выявить все точки использования этого типа в программе (хотя бы тупым поиском). А тип общего назначения, да ещё и широко используемый и неявно выводимый — беда.
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Перекуём баги на фичи!
Re[5]: странный warning
От: Analytic2007 Россия https://www.viva64.com/ru/pvs-studio/
Дата: 17.11.09 13:54
Оценка:
К>Ну и для рефакторинга это мучительно. В специально обученный тип исключения всегда можно подверстать дополнительную информацию, да и выявить все точки использования этого типа в программе (хотя бы тупым поиском). А тип общего назначения, да ещё и широко используемый и неявно выводимый — беда.

Ага. И именно по этому, наш статический анализатор Viva64, входящий в состав PVS-Studio имеет диагностику ошибок связанных с использованием memsize типов в исключениях при переходе на 64-битные системы. Подробнее см. описание диагностических сообщений V115 и V116.
size_t
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.