У меня есть код, который выглядит так:
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>();
}
}
Любые предложения по более чистому способу выразить эту идею установки вещей, если они не нулевые, но не пытаться, если они есть?