Статический анализатор MSVC ругается на две последние функции но не ругается на предыдущие.
Очевидно правила типов работают немного по другому во времени компиляции.
Это правильно по стандарту ?
#include <algorithm>
#include <type_traits>
static_assert(std::is_same_v< decltype(sizeof(1)), size_t >);
static_assert(std::is_same_v< decltype(static_cast<unsigned short>(1) + sizeof(1)), size_t >);
int f_countof(unsigned short i)
{
int l[5] = { 1,2,3,4,5 };
unsigned short j = i + sizeof(l) / sizeof(l[0]); //return j;
}
int f_countof_with_cast(unsigned short i)
{
int l[5] = { 1,2,3,4,5 };
unsigned short j = i + static_cast<size_t>(sizeof(l) / sizeof(l[0]));
return j;
}
int f_countof_with_constexpr(unsigned short i)
{
int l[5] = { 1,2,3,4,5 };
constexpr size_t q = static_cast<size_t>(sizeof(l) / sizeof(l[0]));
unsigned short j = i + q;
return j;
}
int f_countof_with_const(unsigned short i)
{
int l[5] = { 1,2,3,4,5 };
const size_t q = static_cast<size_t>(sizeof(l) / sizeof(l[0]));
unsigned short j = i + q;
return j;
}
int f_countof_with_var(unsigned short i)
{
int l[5] = { 1,2,3,4,5 };
size_t q = static_cast<size_t>(sizeof(l) / sizeof(l[0]));
unsigned short j = i + q; // warning C4267: 'initializing': conversion from 'size_t' to 'unsigned short', possible loss of datareturn j;
}
int f_std_size(unsigned short i)
{
int l[5] = { 1,2,3,4,5 };
unsigned short j = i + std::size(l); // warning C4267: 'initializing': conversion from 'size_t' to 'unsigned short', possible loss of datareturn j;
}
Здравствуйте, _NN_, Вы писали:
_NN>Статический анализатор MSVC ругается на две последние функции но не ругается на предыдущие. _NN>Очевидно правила типов работают немного по другому во времени компиляции.
Я так подозреваю, что компиляторы вычисляют константы на этапе компиляции и видят, что результат не выходит за пределы предствавления unsigned short, поэтому предупреждать не нужно.
Попробуйте объявить вместо int l[5], скажем int l[70000].
_NN>Это правильно по стандарту ?
ЕМНИП warning'и стандартом не описываются.
Опытным путём выяснилось , что переменная const/constexpr так же как и sizeof не вызывает проблем у статического анализатора:
template <typename T>
const size_t S = 0;
template <typename T, size_t N>
const auto S<T[N]> = N;
// Или
// template <typename T, size_t N>
// constexpr size_t S<T[N]> = N;void f()
{
int q[] = { 1 };
[[maybe_unused]] unsigned short a = S<decltype(q)>; // OK
}
Однако в случае с функцией фокус не проходит:
constexpr size_t w() { return 1; }
constexpr size_t e = 1;
void g()
{
[[maybe_unused]] unsigned short a = e; // OK
[[maybe_unused]] unsigned short b = w(); // conversion from 'size_t' to 'unsigned short', possible loss of data
}
Такой вариант не работает потому как std::size возвращает size_t и всё выражение снова получает тип size_t.
Здравствуйте, _NN_, Вы писали:
_NN>Есть идеи как для массивов использовать переменную, а в остальных случаях функцию ?
Я не совсем понимаю, что вы пытаестесь сделать и зачем. Если у вас функция возвращает size_t, то без знания возможных пределов возвращаемого значения в unsigned short результат её выполнения присваивать нельзя. А если пределы известны, то почему просто не сделать static_cast<unsigned short>(::std::size(c))? И вообще, зачем unsigned short ? Это попытка сэкономит пару байтов на стеке?
Здравствуйте, B0FEE664, Вы писали:
_NN>>Есть идеи как для массивов использовать переменную, а в остальных случаях функцию ?
BFE>Я не совсем понимаю, что вы пытаестесь сделать и зачем. Если у вас функция возвращает size_t, то без знания возможных пределов возвращаемого значения в unsigned short результат её выполнения присваивать нельзя. А если пределы известны, то почему просто не сделать static_cast<unsigned short>(::std::size(c))? И вообще, зачем unsigned short ? Это попытка сэкономит пару байтов на стеке?
Это попытка усмирить статический анализатор.
Есть C API принимает unsigned short.
Если писать f(sizeof(a)) то нет проблем, а вот f(std::size(a)) ругается.
Пока решил через функцию выбирающую минимальный тип через if constexpr.
Здравствуйте, Alexander G, Вы писали:
AG>Перегрузки с разными возвращаемыми типами:
В общем выяснилось, что анализатор не умеет делать подстановки constexpr функций и всегда жалуется, а с переменными умеет.
Похоже фичу в язык добавили, а обвязку вокруг забыли.