c #struct #c 17
#c #структура #c 17
Вопрос:
Я пытаюсь инициализировать необязательную структуру. Таким образом, я хотел бы в идеале иметь несколько операторов if для каждой переменной. Например, это мой текущий код;
struct FooBar {
myObj1 foo;
std::optional<myObj2> bar;
};
static std::optional<FooBar> globalFoo;
void Set(std::optional<int> x, std::optional<int> y)
{
if (x amp;amp; y)
{
globalFoot = FooBar{ .foo = {*x}, .bar = {*y} };
}
else if (x amp;amp; !y)
{
globalFoot = FooBar{ .foo = {*x} };
}
else if (!x amp;amp; y)
{
globalFoot = FooBar{.bar = {*y} };
}
}
и я хотел бы как-то упростить это, чтобы
void Set(std::optional<int> x, std::optional<int> y)
{
globalFoot = FooBar{ /* if x.has_value()*/ .foo = {x}, /* if y.has_value() */ .bar = {y} };
}
Я открыт для других предложений, однако Set
функция также должна иметь необязательные входные данные и глобальную переменную.
Комментарии:
1.
globalFoo = FooBar{ .foo = {x.value_or({})}, .bar = {y.value_or({})} };
?2. Ваш текущий код не гарантирует присвоение
globalFoot
/globalFoo
(опечатка?). Замена его одним присваиванием не сможет воспроизвести ту же логику.3. Кажется
y
, нам нужно, вместоvalue_or
,optional::transform
(C 23), но свободная функция может заменить ее раньше.4.
value_or
является достойным вариантом. Однако я забыл упомянуть, что мне нужно выполнить немного больше операций над этим. НапримерglobalFoot = FooBar{ .foo = {*x i}, .bar = {*y i *2} };
5. Затем посмотрите на
transform
/and_then
(или перепишите их как свободную функцию), чтобы решить вашу проблему.
Ответ №1:
Чтобы упростить ситуацию, я бы, вероятно, меньше использовал std::optional
. Возможно, вы можете использовать специальные значения, такие как 0 или -1, хранящиеся в целых числах, или отдельные логические флаги. Вы можете записывать непосредственно в эти целые числа и логические значения вместо создания Set
функции. Но это только мое мнение, и я не знаю всех ваших требований или для чего на самом деле используется этот код.
Если мы предположим, что ваши глобальные переменные и интерфейс спроектированы именно так, как вы хотите, и вам просто нужен способ упростить вашу Set
функцию без изменения ее поведения, вот что вы можете сделать:
#include <optional>
struct FooBar {
int foo;
std::optional<int> bar;
};
static std::optional<FooBar> globalFoo;
void Set(std::optional<int> x, std::optional<int> y)
{
if (!x amp;amp; !y) { return; }
globalFoo = {};
if (x) { globalFoo->foo = *x; }
globalFoo->bar = y;
}
(Кстати, myObj1
и myObj2
не определены в вашем вопросе, поэтому было не совсем ясно, что это такое. Я просто предположил, что они оба были другими именами int
.)
Как и в предыдущем коде, у вас должен был быть комбинаторный взрыв случаев для выражения. Теперь у нас просто есть немного простого кода для установки каждого элемента вместо отдельного рассмотрения всех этих случаев.