Тип sizeof
От: _NN_ www.nemerleweb.com
Дата: 09.03.20 13:00
Оценка:
Статический анализатор 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 data

    return 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 data

    return j;
}
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: Тип sizeof
От: B0FEE664  
Дата: 09.03.20 13:11
Оценка: 10 (1)
Здравствуйте, _NN_, Вы писали:

_NN>Статический анализатор MSVC ругается на две последние функции но не ругается на предыдущие.

_NN>Очевидно правила типов работают немного по другому во времени компиляции.

Я так подозреваю, что компиляторы вычисляют константы на этапе компиляции и видят, что результат не выходит за пределы предствавления unsigned short, поэтому предупреждать не нужно.
Попробуйте объявить вместо int l[5], скажем int l[70000].

_NN>Это правильно по стандарту ?

ЕМНИП warning'и стандартом не описываются.
И каждый день — без права на ошибку...
Re[2]: Тип sizeof
От: _NN_ www.nemerleweb.com
Дата: 10.03.20 06:06
Оценка:
Здравствуйте, B0FEE664, Вы писали:

Опытным путём выяснилось , что переменная 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.
#define MY_SIZE(c) \
    (std::is_array_v<decltype(c)> ? S<decltype(c)> : ::std::size(c))


Есть идеи как для массивов использовать переменную, а в остальных случаях функцию ?
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[3]: Тип sizeof
От: B0FEE664  
Дата: 10.03.20 11:59
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Есть идеи как для массивов использовать переменную, а в остальных случаях функцию ?


Я не совсем понимаю, что вы пытаестесь сделать и зачем. Если у вас функция возвращает size_t, то без знания возможных пределов возвращаемого значения в unsigned short результат её выполнения присваивать нельзя. А если пределы известны, то почему просто не сделать static_cast<unsigned short>(::std::size(c))? И вообще, зачем unsigned short ? Это попытка сэкономит пару байтов на стеке?
И каждый день — без права на ошибку...
Re[4]: Тип sizeof
От: _NN_ www.nemerleweb.com
Дата: 10.03.20 12:31
Оценка:
Здравствуйте, 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.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[3]: Тип sizeof
От: Alexander G Украина  
Дата: 10.03.20 20:48
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Здравствуйте, B0FEE664, Вы писали:



_NN>Есть идеи как для массивов использовать переменную, а в остальных случаях функцию ?


Перегрузки с разными возвращаемыми типами:

template<std::size_t N>
struct constant_size { enum { value = N }; };

struct variable_size { std::size_t value; };

template<class T>
constexpr constant_size<sizeof(T)> size(T v) { return {}; }

template<class T, std::size_t N>
variable_size  size(T (&v) [N]) 
{
    return { std::end(v) - std::begin(v) };
}

int main() {
    short a;
    a = size(a).value;
    std::cout << a << '\n';
    short b[3];
    a = size(b).value;
    std::cout << a << '\n';
    return 0;
}
Русский военный корабль идёт ко дну!
Re[4]: Тип sizeof
От: _NN_ www.nemerleweb.com
Дата: 11.03.20 07:06
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Перегрузки с разными возвращаемыми типами:

В общем выяснилось, что анализатор не умеет делать подстановки constexpr функций и всегда жалуется, а с переменными умеет.
Похоже фичу в язык добавили, а обвязку вокруг забыли.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[5]: Тип sizeof
От: Alexander G Украина  
Дата: 11.03.20 08:47
Оценка:
Здравствуйте, _NN_, Вы писали:


_NN>В общем выяснилось, что анализатор не умеет делать подстановки constexpr функций



Ну тогда через Integer Type Selection вотктнуть нужный тип:

template<std::size_t N>
struct constant_size { static const typename boost::uint_value_t<N>::least value = N; };

struct variable_size { std::size_t value; };

template<class T, std::size_t N>
constant_size<T> size(T (&v) [N]) { return {}; }

template<class T>
variable_size  size(T (&v)) 
{
    return { std::end(v) - std::begin(v) };
}

...

size(a).value;


boost::uint_value_t может быть реализован без constexrp функций на std::conditional

template<std::size_t N>
struct uint_value_t
{
   typedef typename std::conditional<
        (N < 256), 
            std::uint8_t, 
            std::conditional<(N < 65536), 
                std::uint16_t, 
                ... > >::type least;
}
Русский военный корабль идёт ко дну!
Отредактировано 11.03.2020 9:02 Alexander G . Предыдущая версия . Еще …
Отредактировано 11.03.2020 8:50 Alexander G . Предыдущая версия .
Отредактировано 11.03.2020 8:49 Alexander G . Предыдущая версия .
Отредактировано 11.03.2020 8:48 Alexander G . Предыдущая версия .
Re[6]: Тип sizeof
От: _NN_ www.nemerleweb.com
Дата: 11.03.20 09:08
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Ну тогда через Integer Type Selection вотктнуть нужный тип:


Я так и сделал, но без буста, потому что его не хотят видеть в коде
http://rsdn.nemerleweb.com
http://nemerleweb.com
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.