Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.60/5: Рейтинг темы: голосов - 5, средняя оценка - 4.60
JinKey
0 / 0 / 0
Регистрация: 12.10.2014
Сообщений: 9
Завершенные тесты: 1
1

Определение размера типа переданного в шаблон

20.10.2016, 13:29. Просмотров 944. Ответов 20
Метки нет (Все метки)

Доброй день. Подскажите почему, sizeof в данном случае некорректно определяет размер структуры
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct Preheader_1
{
    uint8_t packet_length;
};
 
const Preheader_1* preheader_1 = (const Preheader_1*)Data;
offset_by_preheader(Data, preheader_1);
 
template <class Type_preheader>
void offset_by_preheader(Class &data, Type_preheader preheader)
{
    if (preheader->packet_length == (data.LenData - sizeof(Type_preheader)))
    {
        ...
    }
}
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
20.10.2016, 13:29
Ответы с готовыми решениями:

Определение размера массива
Привет всем у меня несколько вопросов по языку си (компилятор gcc). 1) Есть,...

Определение размера массива
Код: template &lt;class T,int N&gt; int arr_sz(T (&amp;arr)) {return N;} void...

определение размера матрицы
Имеется массив с матрицами(трехмерный массив), над матрицами из этого массива...

Определение размера файла
Здравствуйте, я учусь на программиста, нужна помощь в программе. #include...

Определение размера массива + sizeof
Массив из 6 чисел: sizeof возвращает 24 байта. Тот же массив вызван функцией...

20
hoggy
Нарушитель
Эксперт С++
7081 / 3125 / 647
Регистрация: 15.11.2014
Сообщений: 7,172
Завершенные тесты: 1
20.10.2016, 13:31 2
Цитата Сообщение от JinKey Посмотреть сообщение
почему, sizeof в данном случае некорректно определяет размер структуры
ни почему.

в данном случае sizeof определяет размер структуры корректно.
0
DemolitionMan
129 / 155 / 87
Регистрация: 06.04.2016
Сообщений: 992
20.10.2016, 13:34 3
Цитата Сообщение от JinKey Посмотреть сообщение
sizeof(Type_preheader)))
- я так полагаю, что неизвестно размер типа, потому что он не указан.
0
JinKey
0 / 0 / 0
Регистрация: 12.10.2014
Сообщений: 9
Завершенные тесты: 1
20.10.2016, 13:38  [ТС] 4
Ну для этого я и сделал template < class T>, потому что у меня может быть несколько примерно однотипных структур, я передаю экземпляр структуры или этого не достаточно и нужно создавать специализацию?
0
DemolitionMan
129 / 155 / 87
Регистрация: 06.04.2016
Сообщений: 992
20.10.2016, 13:39 5
Так он должен размер определять, когда ты конкретный тип пихнешь в переменную Type_preheader. Какой тип ты в нее пихаешь?
0
JinKey
0 / 0 / 0
Регистрация: 12.10.2014
Сообщений: 9
Завершенные тесты: 1
20.10.2016, 13:47  [ТС] 6
Кажется я немножко догнал. Пихая я туда же не экземпляр типа структуры, а экземпляр указателя на структуры. Но как тогда определить в функции размер именно структуры или придется отдельно передавать параметром размер?

Структуры:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
struct Preheader_1
{
    uint8_t packet_length;
};
 
struct Preheader_1_heavy
{
    uint16_t packet_length;
};
 
struct Preheader_3
{
    uint8_t static_field;
    uint8_t packet_length;
};
 
struct Preheader_3_heavy
{
    uint8_t static_field;
    uint16_t packet_length;
};
Инициализация нескольких структур:
C++
1
2
3
4
        const Preheader_1* preheader_1 = (const Preheader_1*)pack.Data;
        const Preheader_1_heavy* preheader_1_heavy = (const Preheader_1_heavy*)pack.Data;
        const Preheader_3* preheader_3 = (const Preheader_3*)pack.Data;
                const Preheader_3_heavy* preheader_3_heavy = (const Preheader_3*)pack.Data;
Передача в функцию:
C++
1
2
3
4
            offset_by_preheader(pack, preheader_1);
            offset_by_preheader(pack, preheader_1_heavy);
            offset_by_preheader(pack, preheader_3);
            offset_by_preheader(pack, preheader_3_heavy);
0
hoggy
Нарушитель
Эксперт С++
7081 / 3125 / 647
Регистрация: 15.11.2014
Сообщений: 7,172
Завершенные тесты: 1
20.10.2016, 13:54 7
Цитата Сообщение от JinKey Посмотреть сообщение
Но как тогда определить в функции размер именно структуры или придется отдельно передавать параметром размер?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <iostream>
 
struct Preheader_1
{
    uint8_t packet_length;
};
 
struct Preheader_1_heavy
{
    uint16_t packet_length;
};
 
struct Preheader_3
{
    uint8_t static_field;
    uint8_t packet_length;
};
 
struct Preheader_3_heavy
{
    uint8_t static_field;
    uint16_t packet_length;
};
 
struct Class
{
    size_t LenData = 0;
};
 
template <class T>
void offset_by_preheader(const Class& data, const T& preheader)
{
    if (preheader.packet_length == (data.LenData - sizeof(T)))
        std::cout <<"true\n";
    else
        std::cout <<"false\n";
}
 
template <class T>
void offset_by_preheader(const Class& data, const T* preheader)
    { offset_by_preheader(data, *preheader); }
 
 
int main()
{
    std::cout << "Hello, world!\n";
    
    Class data;
    Preheader_3_heavy p3h;
    offset_by_preheader(data, p3h);
}
0
JinKey
0 / 0 / 0
Регистрация: 12.10.2014
Сообщений: 9
Завершенные тесты: 1
20.10.2016, 13:55  [ТС] 8
Всем спасибо, немного потерялся. Передавался указатель, в итоге sizeof работал действительно корректно. Решил передать размер через отдельный параметр.
0
MrGluck
Модератор
Эксперт CЭксперт С++
8084 / 4941 / 1431
Регистрация: 29.11.2010
Сообщений: 13,392
20.10.2016, 13:57 9
Либо так:
C++
1
2
offset_by_preheader(*preheader_1);
offset_by_preheader(*preheader_1_heavy);
Либо так:
C++
1
2
template <class Type_preheader>
void offset_by_preheader(Type_preheader *preheader)
1
castaway
Эксперт С++
4930 / 3037 / 453
Регистрация: 10.11.2010
Сообщений: 11,116
Записей в блоге: 10
Завершенные тесты: 1
20.10.2016, 13:58 10
DemolitionMan, Type_preheader - это тип, а не переменная.
0
DemolitionMan
129 / 155 / 87
Регистрация: 06.04.2016
Сообщений: 992
20.10.2016, 14:15 11
Я так думаю, что это переменный тип.
0
hoggy
Нарушитель
Эксперт С++
7081 / 3125 / 647
Регистрация: 15.11.2014
Сообщений: 7,172
Завершенные тесты: 1
20.10.2016, 14:21 12
Цитата Сообщение от JinKey Посмотреть сообщение
Решил передать размер через отдельный параметр.
это - ошибка проектирования.

нельзя просто так брать и передавать избыточную информацию,
которая к тому же теоретически может содержать неверные сведения.

размер типа можно определить автоматически.
в сообщении #7 я показал вам,
как это можно сделать.

всегда нужно стремиться сводить к минимуму
количество аргументов функций.
это сделает код проще,
и сведет количество возможных ошибок к минимуму.
1
JinKey
0 / 0 / 0
Регистрация: 12.10.2014
Сообщений: 9
Завершенные тесты: 1
20.10.2016, 14:25  [ТС] 13
hoggy, хорошо, большое спасибо за корректное объяснение, воспользуюсь вашем советом и избавлюсь от избыточного параметра
0
hoggy
Нарушитель
Эксперт С++
7081 / 3125 / 647
Регистрация: 15.11.2014
Сообщений: 7,172
Завершенные тесты: 1
20.10.2016, 15:00 14
JinKey,
здесь ошибка:

C++
1
2
void offset_by_preheader(const Class& data, const T* preheader)
    { offset_by_preheader(data, &preheader); }
должно быть так:

C++
1
2
void offset_by_preheader(const Class& data, const T* preheader)
    { offset_by_preheader(data, *preheader); }
нужно попросить модераторов что бы подправили #7
0
Croessmah
20.10.2016, 15:07
  #15

Не по теме:

Цитата Сообщение от hoggy Посмотреть сообщение
нужно попросить модераторов что бы подправили #7
Сделал. Проверьте. :)

0
JinKey
0 / 0 / 0
Регистрация: 12.10.2014
Сообщений: 9
Завершенные тесты: 1
20.10.2016, 15:12  [ТС] 16
hoggy, Я так понял, могу не использовать данную функцию:
C++
1
2
3
4
5
template <class Type_preheader>
void offset_by_preheader(Class & data, Type_preheader * preheader)
{
    offset_by_preheader(data, *preheader);
}
Если сделаю вот так:
C++
1
2
const Preheader_1 = *(reinterpret_cast<const Preheader_1*>(pack.Data));
offset_by_preheader(pack, preheader_1);
Оставив лишь:
C++
1
2
3
4
5
6
7
8
9
template <class Type_preheader>
void offset_by_preheader(Class &data, Type_preheader& preheader)
{
    if (preheader.packet_length == (data.LenData - sizeof(Type_preheader)))
    {
        data.Data     += sizeof(Type_preheader);
        data.LenData -= sizeof(Type_preheader);
    }
}
Или здесь есть какая-то тонкость?
0
Croessmah
++Ͻ
14610 / 8364 / 1576
Регистрация: 27.09.2012
Сообщений: 20,557
Записей в блоге: 2
Завершенные тесты: 1
20.10.2016, 15:19 17
hoggy, и const, наверное, убрать надо:
C++
1
2
void offset_by_preheader(const Class& data, T* preheader)
    { offset_by_preheader(data, *preheader); }
иначе получим ошибку для указателей не на константы.
0
hoggy
Нарушитель
Эксперт С++
7081 / 3125 / 647
Регистрация: 15.11.2014
Сообщений: 7,172
Завершенные тесты: 1
20.10.2016, 15:21 18
Лучший ответ Сообщение было отмечено JinKey как решение

Решение

Цитата Сообщение от Croessmah Посмотреть сообщение
Сделал. Проверьте.
спасибо.
проверил - не работает!

совсем забыл, что константная ссылка в шаблонах любит выносить мозг

вот правильная версия:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <iostream>
 
struct Preheader_1
{
    uint8_t packet_length;
};
 
struct Preheader_1_heavy
{
    uint16_t packet_length;
};
 
struct Preheader_3
{
    uint8_t static_field;
    uint8_t packet_length;
};
 
struct Preheader_3_heavy
{
    uint8_t static_field;
    uint16_t packet_length;
};
 
struct Class
{
    size_t LenData = 0;
};
 
template <class T>
void offset_by_preheader(const Class& data, const T& preheader)
{
    if (preheader.packet_length == (data.LenData - sizeof(T)))
        std::cout <<"true\n";
    else
        std::cout <<"false\n";
}
 
template <class T>
void offset_by_preheader(const Class& data, const T* const  preheader)
    { offset_by_preheader(data, *preheader); }
 
 
template <class T>
void offset_by_preheader(const Class& data, T* const  preheader)
    { offset_by_preheader(data, *preheader); }
 
int main()
{
    std::cout << "Hello, world!\n";
    
    Class data;
    Preheader_3_heavy p3h;
    offset_by_preheader(data, p3h);
    offset_by_preheader(data, &p3h);
}
Добавлено через 1 минуту
Цитата Сообщение от Croessmah Посмотреть сообщение
и const, наверное, убрать надо
явный const лучше неявного, я думаю.
0
Croessmah
20.10.2016, 15:22
  #19

Не по теме:

Цитата Сообщение от hoggy Посмотреть сообщение
явный const лучше неявного
От перестановки const суть меняется.
Изначально он у Вас был в другом месте,
посему я предложил совсем его убрать. :)

0
hoggy
Нарушитель
Эксперт С++
7081 / 3125 / 647
Регистрация: 15.11.2014
Сообщений: 7,172
Завершенные тесты: 1
20.10.2016, 15:28 20
Цитата Сообщение от Croessmah Посмотреть сообщение
Изначально он у Вас был в другом месте,
вы не поняли.

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

если скормить им обычный указатель на изменяемый объект,
то выбор будет в пользу константной ссылки,
а не в пользу указателя на неизменяемый объект.

причем на разных компиляторах я наблюдал разное поведение.

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

но думаю в данном случае SFINAE - оверхед.

и да, квалификатор const должен быть явным там,
где ожидаются неизменяемые данные.
1
20.10.2016, 15:28
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.10.2016, 15:28

Определение размера одномерного массива
Добрый день. Необходимо задать размер одномерного массива. В цикле for стоит...

Определение размера массива в функции
Всем доброго дня ! Подскажите пожалуйста, как можно определить размер...

Определение размера char** argv
Есть массив строк char** argv где я знаю число строк argc for (int i = 0; i &lt;...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru