Есть ли причина, по которой VectorLength возвращает size_t, а Vector::size возвращает uoffset_t?

#c #flatbuffers

Вопрос:

Это иногда вызывает проблемы с 64-разрядной компиляцией. Если нет особой причины, я думаю, что было бы лучше иметь согласованный тип индекса для VectorLength() и Vector::size().

В этом примере вызов print_first_n_of_inventory с длиной вектора требует приведения.

 #include <flatbuffers/flatbuffers.h>
#include <tests/monster_test_generated.h>
#include <iostream>

using namespace flatbuffers;
using namespace MyGame::Example;

void print_first_n_of_inventory(const Vector<uint8_t> * pInventory, uoffset_t n)
{
    for (uoffset_t i = 0; i < n;   i)
    {
        auto val = pInventory->Get(i);
        std::cout << val << "n";
    }
}

int main(int, char * argv[])
{
    auto * pMonster = GetMonster(argv[1]);
    auto * pInventory = pMonster->inventory();

    print_first_n_of_inventory(pInventory, 2);
    print_first_n_of_inventory(pInventory, pInventory->size());

    // warning C4267: 'argument': conversion from 'size_t' to 'flatbuffers::uoffset_t', possible loss of data
    print_first_n_of_inventory(pInventory, VectorLength(pInventory));

    return 0;
}

 

Комментарии:

1. VectorLength проверяет, что указанный указатель отсутствует nullptr , и преобразует uoffset_t возвращенное size() значение в size_t . Возможно, чтобы упростить его использование в контекстах, отличных от flatbuffer, где size_t ожидается a, но, как вы заметили, это кажется ненужным. Было бы лучше использовать uoffset_t и то, и другое. Я бы использовал функцию-член size() напрямую, когда я уверен pInventory , что это не nullptr так, и uoffset_t (что всегда uint32_t ) требуется. Или добавьте это: template<typename T> static inline auto MyVectorLength(const Vector<T>* v) { return v ? v->size() : 0U; } и используйте это вместо этого.

2. Мой шаблон функции замены должен был быть следующим: template<typename T> static inline auto MyVectorLength(const flatbuffers::Vector<T>* v) { return v ? v->size() : 0U; } — Я забыл пространство имен.

Ответ №1:

Да, это прискорбно, но uoffset_t это собственный тип того, как длина хранится в буферах, которые всегда 32-разрядные. Казалось, что лучше всего предоставить этот собственный тип, чем конвертировать в size_t для пользователя, так как это приведет к двойному преобразованию в случае, когда 32-разрядные на самом деле были бы желательны.

Комментарии:

1. Как вы думаете, это можно и нужно изменить? Это может привести к другому типу, выведенному с помощью автоматического вывода типа или кода шаблона, но в противном случае должно быть неявно преобразовано в size_t, как сейчас внутри функции.