Инициализация через initializer_list и protected/private
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 30.05.22 18:13
Оценка:
Здравствуйте!

Код:
#include <iostream>

struct Test
{
    int i1;
    int i2;

protected:    

    int i3;

public:

    int getI3() const
    {
        // ...
    }

    void setI3( int vi3 )
    {
        i3 = vi3;
    }
};

int main()
{
    Test t{ 1, 2, 3 };
    // Test t = { 1, 2, 3 };

    std::cout << t.i1 << ", " << t.i2 << "\n";

    return 0;
}



Он, само собой, не собирается. Что я хочу — я хочу, чтобы при различных комбинациях i1/i2/i3 метод getI3() возвращал либо сам i3, либо результат каких-либо вычислений. Поэтому я сделал это поле защищенным.
Но — я хочу забить какой-то конфиг из map of map'ов с листами Test'а, в тч и чтобы i3 был в некоторых случаях инициализирован не по дефолту. В рантайме я этот конфиг могу обновить, а могу и использовать, как есть. Для этого удобен синтаксис initializer_list'а. При этом чего-то лищнего писать особо не хочется.
Что-то не пойму, как такое провернуть

ЗЫ А чего, http://ideone.com/ — ффсё? Давно не заходил туда, это он от СВО поломался?
Маньяк Робокряк колесит по городу
Re: Инициализация через initializer_list и protected/private
От: Muxa  
Дата: 30.05.22 19:27
Оценка:
Добавь конструктор:
    Test (int vi1, int vi2, int vi3){ i1 = vi1; i2 = vi2; i3 = vi3; }
Re[2]: Инициализация через initializer_list и protected/private
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 30.05.22 19:40
Оценка:
Здравствуйте, Muxa, Вы писали:

M>Добавь конструктор:

M>
    Test (int vi1, int vi2, int vi3){ i1 = vi1; i2 = vi2; i3 = vi3; }


а) без лишней писанины уже не получается
б) не надо ли тогда и другие конструкторы описывать хотя бы как = default?
Маньяк Робокряк колесит по городу
Re[3]: Инициализация через initializer_list и protected/priv
От: rg45 СССР  
Дата: 30.05.22 20:23
Оценка: 4 (1)
Здравствуйте, Marty, Вы писали:

M>>
    Test (int vi1, int vi2, int vi3){ i1 = vi1; i2 = vi2; i3 = vi3; }


M>а) без лишней писанины уже не получается

M>б) не надо ли тогда и другие конструкторы описывать хотя бы как = default?

Так добавь значения по умолчанию к формальным параметрам конструктора и инициализация получится по форме очень похожа на агрегатную:

http://coliru.stacked-crooked.com/a/907b00964ddf04ef

#include <iostream>

struct Test
{
    int i1;
    int i2;

protected:    

    int i3;

public:

    Test(int i1 = {}, int i2 = {}, int i3 = {}) : i1(i1), i2(i2), i3(i3) {}

    int getI3() const { return i3; }
    void setI3( int vi3 ) { i3 = vi3; }
};

int main()
{
    Test x;
    Test y{1};
    Test z{1, 2};


    Test t{ 1, 2, 3 };
    //Test t = { 1, 2, 3 };

    std::cout << t.i1 << ", " << t.i2 << "\n";
}
--
Отредактировано 30.05.2022 20:29 rg45 . Предыдущая версия . Еще …
Отредактировано 30.05.2022 20:28 rg45 . Предыдущая версия .
Re[3]: Инициализация через initializer_list и protected/private
От: Muxa  
Дата: 30.05.22 20:25
Оценка:
M>а) без лишней писанины уже не получается
Ну, а как ты хотел.

M>б) не надо ли тогда и другие конструкторы описывать хотя бы как = default?

Смотри сам как объекты используются.
Re[4]: Инициализация через initializer_list и protected/priv
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 30.05.22 21:06
Оценка:
Здравствуйте, rg45, Вы писали:

M>>>
    Test (int vi1, int vi2, int vi3){ i1 = vi1; i2 = vi2; i3 = vi3; }


M>>а) без лишней писанины уже не получается

M>>б) не надо ли тогда и другие конструкторы описывать хотя бы как = default?

R>Так добавь значения по умолчанию к формальным параметрам конструктора и инициализация получится по форме очень похожа на агрегатную:


Вопрос в том, что не надо ли на всякий случай все конструкторы выписывать
Маньяк Робокряк колесит по городу
Re[4]: Инициализация через initializer_list и protected/private
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 30.05.22 21:08
Оценка: :)
Здравствуйте, Muxa, Вы писали:

M>>а) без лишней писанины уже не получается

M>Ну, а как ты хотел.

Раз-два — и в дамки


M>>б) не надо ли тогда и другие конструкторы описывать хотя бы как = default?

M>Смотри сам как объекты используются.

Старею. Может в шарпея перекрасится Обленился
Маньяк Робокряк колесит по городу
Re[5]: Инициализация через initializer_list и protected/priv
От: rg45 СССР  
Дата: 31.05.22 06:49
Оценка:
Здравствуйте, Marty, Вы писали:

M>Вопрос в том, что не надо ли на всякий случай все конструкторы выписывать


В этом нет нужды (если основываться лишь на примере). Единственный определенный пользователем конструктор одновременно является и конструктором по умолчанию. Все остальные специальные функции-члены (конструкторы, деструктор и операторы присваивания) по-прежнему генерируются компилятором.

P.S. Это в том случае, когда пользователь определяет какую-нибудь специальную функцию-член (например, конструктор перемещения или копирования), тогда он может скрывать другие специальные функции-члены или делать их удаленными и может потребоваться определить их дополнительно. А определенный пользователем дефолтный конструктор никак не влияет на другие функции-члены, поэтому прописывать их явно нет необходимости, если сгенерированный компилятором вариант устраивает, разумеется.

Ну и помимо этого существуют еще и заповеди типа: "если вы определили конструктор копирования, то определите также и копирующий оператор присваивания" и т.п. Но все это не имеет отношения к случаю, описанному в твоем примере.
--
Отредактировано 31.05.2022 9:06 rg45 . Предыдущая версия . Еще …
Отредактировано 31.05.2022 9:01 rg45 . Предыдущая версия .
Отредактировано 31.05.2022 8:32 rg45 . Предыдущая версия .
Отредактировано 31.05.2022 8:31 rg45 . Предыдущая версия .
Re: Инициализация через initializer_list и protected/private
От: AleksandrN Россия  
Дата: 03.06.22 22:17
Оценка:
Здравствуйте, Marty, Вы писали:

M>Для этого удобен синтаксис initializer_list'а. При этом чего-то лищнего писать особо не хочется.

M>Что-то не пойму, как такое провернуть

    Test(const std::initializer_list<int> &init)
    {
        if (init.size() < 3)
            throw std::out_of_range("Invalid size of initializer list.\n");
        auto it = init.begin();
        i1 = *it;
        i2 = *(++it);
        i3 = *(++it);
    }
Re: Можно через protected/private наследование от структур с
От: Sm0ke Россия http://ksi.ru.net/
Дата: 06.06.22 06:20
Оценка:
Здравствуйте, Marty

// Группируем свойства по базовым структурам.

struct props_public {
    int m1 = 11, m2 = 12, m3 = 13;
};

struct props_protected {
    int m4 = 14, m5 = 15, m6 = 16;
};

struct props_private {
    int m7 = 17, m8 = 18, m9 = 19;
};

// Вспоминаем, что есть не только public наследование.

class my_class :
    public props_public,
    protected props_protected,
    private props_private
{
public:
    my_class(
        const props_public & p_pub = {},
            const props_protected & p_prot = {},
            const props_private & p_priv = {}
    ) : props_public(p_pub), props_protected(p_prot), props_private(p_priv) {}
};

int main() {
    my_class({1}, {4}, {7});
    return 0;
}


Тут есть преимущество, что дефолтные значения свойств не надо дублировать и в конструкторе тоже.
Отредактировано 06.06.2022 6:38 Sm0ke . Предыдущая версия .
Re[2]: Инициализация через initializer_list и protected/private
От: Sm0ke Россия http://ksi.ru.net/
Дата: 06.06.22 06:22
Оценка:
Здравствуйте, AleksandrN, Вы писали:

AN>Здравствуйте, Marty, Вы писали:


M>>Для этого удобен синтаксис initializer_list'а. При этом чего-то лищнего писать особо не хочется.

M>>Что-то не пойму, как такое провернуть

AN>
AN>    Test(const std::initializer_list<int> &init)
AN>    {
AN>        if (init.size() < 3)
AN>            throw std::out_of_range("Invalid size of initializer list.\n");
AN>        auto it = init.begin();
AN>        i1 = *it;
AN>        i2 = *(++it);
AN>        i3 = *(++it);
AN>    }

AN>


А если свойства разных типов?
Re[2]: Можно через protected/private наследование от структур со свойствами по г
От: Sm0ke Россия http://ksi.ru.net/
Дата: 06.06.22 06:37
Оценка:
Если нужны свойства тяжёлых типов, то желательно определить конструктор и через мув тоже.

Или через perfect forwarding. Но тогда придётся указывать типы при инициализации.

struct props_public { int m1; };

struct props_private {
    std::vector<int> m2;
    // Тут компилятор сгенерирует мув конструктор, который мувы дёргает почленно.
};

class my_class : public props_public, private props_private {
public:
    template <typename T_pub, typename T_priv>
    my_class(T_pub && p_pub, T_priv && p_priv) : props_public( std::forward<T_pub>(p_pub) ), props_private( std::forward<T_priv>(p_priv) ) {}
};

int main() {
    my_class v_test(props_public{0}, props_private{ {1, 2, 3} });
    return 0;
}
Re[3]: Инициализация через initializer_list и protected/private
От: AleksandrN Россия  
Дата: 08.06.22 21:44
Оценка:
Здравствуйте, Sm0ke, Вы писали:

S>А если свойства разных типов?


Тогда такое решение не подойдёт. Но топиктстартер про типы ничего не писал, а в примере тип один.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.