Я хочу преобразовать массив беззнаковых коротких значений в JSON, используя библиотеку nlohmann.
Мой тип переменной — это указатель на список беззнаковых коротких значений, завершающийся нулем. Типоопределение такое:
typedef unsigned short USHORT;
typedef USHORT * LPUSHORT;
Я подготовил эту перегрузку для удобной обработки этого типа:
void to_json(nlohmann::json &resultJson, LPUSHORT lp)
{
while (*lp != NULL)
{
nlohmann::json single = (*lp);
resultJson["list"].push_back(single);
lp++;
}
}
Но когда это делаешь
resultJson["nids"] = (LPUSHORT) lp->nids;
Я получаю ошибку:
no operator matches these operands
operand types are: nlohmann::json_abi_v3_11_2::basic_json<std::map, std::vector, std::string, bool, int64_t, uint64_t, double, std::allocator, nlohmann::json_abi_v3_11_2::adl_serializer, std::vector<uint8_t, std::allocator<uint8_t>>, void> = LPUSHORT
Я также пробовал это с другими определениями типов, которые представляют собой структуры short, int, char*,... все это работает. Но не напрямую при преобразовании LPUSHORT.
Эта библиотека предназначена для работы с C++, а не C. Поэтому не используйте необработанные указатели для моделирования массивов, а используйте std::vector<std::uint8_t> для хранения ваших данных (json.nlohmann.me/api/basic_json/ array_t)
У вас есть LPUSHORT lp
, а затем lp->nids
, у unsigned short
нет члена nids
...
ADL работает с классами, а не с тривиальными типами. поэтому void to_json(nlohmann::json &resultJson, unsigned short* lp)
не встретишь в технике nlohman.
@Jarod42 Jarod42, оператор ->
имеет более высокий приоритет, чем приведение в стиле C, поэтому (LPUSHORT) lp->nids
будет интерпретироваться как ((LPUSHORT)(lp->nids))
, а не как ((LPUSHORT)lp)->nids
, как вы думаете.
@RemyLebeau: единственный lp
, показанный OP, относится к типу LPUSHORT
. Используйте другое имя, чтобы не запутать читателя при несовпадении типов...
Я не уверен, что это сработает, но попробуйте следующее (C++20 и выше):
#include <algorithm>
#include <span>
auto past_the_end_elem = std::find(std::cbegin((LPUSHORT)lp->nids), std::cend((LPUSHORT)lp->nids), nullptr);
resultJson["nids"] = std::span<USHORT>(std::cbegin((LPUSHORT)lp->nids, past_the_end_elem);
Как уже упоминалось другими, ключом является преобразование массива, например. вектор в первую очередь.
@mazi действительно. Я бы сказал, что главное — сделать это последовательностью (если это поддерживается абстракцией итерации). Указатель не является последовательностью, но указатель со значением, завершающимся нулем (это, по сути, то же самое, что const char * для строк), можно рассматривать как последовательность. Итак, задача состоит в том, чтобы найти конец последовательности и преобразовать ваше значение в одну из таких последовательностей. Если поддерживается std::span, вы избегаете предварительного копирования всех данных в вектор, что потенциально может привести к значительным затратам.
Пожалуйста, предоставьте минимально воспроизводимый пример.