PostgreSQL C++ (pqxx) и значение параметра, если оно не равно NULL

У меня есть код, который выглядит так:

for (const auto& query_result_row : query_result) {
    my_struct.a = query_results_row["a"].as<int>();
    my_struct.b = query_results_row["b"].as<string>();
    // and so forth.
}

В общем, может быть довольно много полей разных типов. И это хорошо, но если выбранное поле имеет значение NULL, это вызовет исключение. Поэтому вместо этого я написал это, что очень неудобно и более чем подвержено ошибкам:

for (const auto& query_result_row : query_result) {
    if (!query_results_row["a"].is_null()) {
        my_struct.a = query_results_row["a"].as<int>();
    }
    if (!query_results_row["ab"].is_null()) {
        my_struct.b = query_results_row["b"].as<string>();
    }
    // and so forth.
}

Ик.

Возможно, подумал я, я мог бы сделать (шаблонную) функцию, которая упрощает это:

for (const auto& query_result_row : query_result) {
    MaybeSet(my_struct.a, query_results_row["a"]);
    MaybeSet(my_struct.b, query_results_row["b"]);
    // and so forth.
}

Проблема здесь в том, что query_results_row["a"] сам по себе является шаблонным типом, и, кроме того, тип as() может не в точности совпадать с типом my_struct (например, разные типы int) и хотя я его сегодня не вижу, это попахивает что-то, что когда-нибудь может привести к непреднамеренному броску.

// Doesn't work.
template <typename valueT, typename postgresFieldT>
void MaybeSet(valueT& my_struct_field, const postgresFieldT& field) {
    if (!field.is_null()) {
        my_struct_field = field.as<valueT>();
    }
}

Любые предложения по более чистому способу выразить эту идею установки вещей, если они не нулевые, но не пытаться, если они есть?


person jma    schedule 24.07.2020    source источник


Ответы (1)


Для будущих поколений: я немного изменил задачу и пришел к простому решению.

template <typename T>
class SetThing {
    // ...
    void MaybeSet(const pqxx::result::field& field) {
        if (!field.is_null()) {
            SetClean(field.as<T>());
        }
    }
    template <typename asT>
    void MaybeSet(const pqxx::result::field& field) {
        if (!field.is_null()) {
            SetClean(field.as<asT>());
        }
    }
    // ...
}

Затем использование становится

SetThing thing;
thing.MaybeSet(query_result_row["dog"]);
thing.MaybeSet<the_cast_type>(query_result_row["complicated"]);

Вторая форма используется для нескольких сложных типов (например, классов), которые я могу создать из чего-то простого (скажем, int или строки), но не являющегося базовым (шаблонным) типом SetThing.

person jma    schedule 29.07.2020