Инициализация структуры C с помощью встроенных операторов If для каждой переменной

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 .)

Как и в предыдущем коде, у вас должен был быть комбинаторный взрыв случаев для выражения. Теперь у нас просто есть немного простого кода для установки каждого элемента вместо отдельного рассмотрения всех этих случаев.