Я использую nlohmann json библиотеку , которая имеет функцию json::get<>()
, чтобы получить значение из json с проверкой типа. Выдает исключение при несовпадении типов. В моем проекте мне нужна проверка ввода json (если все объекты присутствуют, включая правильные типы), поэтому я построил что-то вроде этого:
#include <string>
#include <tuple>
#include <iostream>
#include "nlohmann/json.hpp"
using namespace nlohmann;
template<typename _Tp>
class ValidatorField
{
public:
using type = _Tp;
ValidatorField(const std::string& tp) : fieldName(tp) {}
const std::string& getName() const { return fieldName; }
private:
std::string fieldName;
};
using string_t = ValidatorField<std::string>;
using int_t = ValidatorField<int>;
using bool_t = ValidatorField<bool>;
template<std::size_t N, class... _Ts>
static inline std::enable_if_t<N==0, bool> typeCheck(const json& j, const std::tuple<_Ts...>& tuple) noexcept
{
try
{
if (j.find(std::get<N>(tuple).getName()) != j.end())
{
j[std::get<N>(tuple).getName()].get<std::tuple_element_t<N, std::tuple<_Ts...>>::type>();
return true;
}
return false;
}
catch (std::exception& e)
{
std::cout << e.what() << std::endl;
return false;
}
}
template<std::size_t N, class... _Ts>
static inline std::enable_if_t < 0 < N, bool > typeCheck(const json& j, const std::tuple<_Ts...>& tuple) noexcept
{
try
{
if (j.find(std::get<N>(tuple).getName()) != j.end())
{
j[std::get<N>(tuple).getName()].get<std::tuple_element_t<N, std::tuple<_Ts...>>::type>();
return typeCheck<N-1>(j, tuple);
}
return false;
}
catch (std::exception& e)
{
std::cout << e.what() << std::endl;
return false;
}
}
class object_t
{
public:
template<typename... _Ts>
object_t(const std::string& tp, const std::tuple<_Ts...>& fields, const json& j) : fieldName(tp)
{
std::cout << std::boolalpha << typeCheck<std::tuple_size_v<std::tuple<_Ts...>> - 1, _Ts...>(j, fields) << std::endl;
}
private:
std::string fieldName;
};
int main()
{
json j = json::object();
j["field1"] = "strValue";
j["field2"] = 4;
j["field3"] = 4;
std::cout << j.dump(4) << std::endl;
object_t("branch", std::make_tuple(
string_t {"field1"},
int_t {"field2"},
int_t {"field3"}
), j);
}
, который работает на удивление хорошо - за исключением только clang.
Пример вывода:
{
"field1": "strValue",
"field2": 4,
"field3": 4
}
true
Я пытался скомпилировать его с помощью G CC - что дало следующий результат:
Есть идеи, почему я вижу такое поведение?
РЕДАКТИРОВАТЬ 1 :
Если я удаляю содержимое в скобках [], оно работает просто отлично. Также, если я заменю [std::get<N>(tuple).getName()]
на ["const-string"]
, он тоже будет работать.
Я бы склонялся к вероятности, что это ошибка в G CC