Статический список параметров класса
От: Serg27  
Дата: 02.04.21 08:07
Оценка:
Есть иерархия классов. Каждый класс имеет список имен ему нужных параметров, которые потом как-то используются как внутри класса так и извне его. Этот список постоянный для каждого класса. Причем в списке класса потомка присутствует весь список от базового класса. Написал решение. Упрощенный вариант см. ниже. Но можно ли как-то попроще/поизящней? Много копи-паста и следовательно возможностей ошибок.
Используется VS 2017 с ключом /c++17. Списки не очень большие — максимум несколько десятков элементов. Много классов имеют пустой собственный список (т.е. только от базового класса).

using params_list = std::list<std::string>;
struct B
{
    virtual const params_list & params() const = 0
    {
        return B::params_;
    }
    static const params_list params_;
};
const params_list B::params_{ "b1","b2","b3" };
struct D1 : public B
{
    const params_list & params() const override
    {
        return D1::params_;
    }
    static const  params_list params_;
private:
    static const  params_list my_params_;
};
params_list create_params(params_list base, const  params_list &my)
{
    base.insert(base.end(), my.begin(), my.end());
    return base;
}
const params_list D1::my_params_{ "d1_1" };
const params_list D1::params_{ create_params(B::params_, D1::my_params_) };
struct D2 : public D1
{
    const params_list & params() const override
    {
        return D2::params_;
    }
    static const  params_list params_;
private:
    static const  params_list my_params_;
};
const params_list D2::my_params_{ "d2_1", "d2_2"};
const params_list D2::params_{ create_params(D1::params_, D2::my_params_) };
int main()
{
    B * d1 = new D1;
    B * d2 = new D2;
    for (const auto &p : d1->params()) { std::cout << p << ' '; }
    std::cout << std::endl;
    for (const auto &p : d2->params()) { std::cout << p << ' '; }
    std::cout << std::endl;
}
Re: Голые владеющие указатели, правда?
От: so5team https://stiffstream.com
Дата: 02.04.21 09:57
Оценка: +2
Здравствуйте, Serg27, Вы писали:

S>
S>int main()
S>{
S>    B * d1 = new D1;
S>    B * d2 = new D2;
S>}
S>


Простите, что не по теме вашего вопроса. Но.
По работе временами приходится заглядывать в дебри чужого кода. И, чем более древний и убогий код, тем чаще там встречается вот такое вот: A * p = new A; Более чем верный маркер того, что дальше будет треш, угар и содомия.

Ну ладно в древнем коде. Но, блин, в XXI-ом веке что заставляет писать вот это, когда давным-давно на всех углах говорят, что голые владеющие указатели -- это зло. Тем более, что эти указатели здесь, мягко говоря, вообще не нужны:
int main()
{
  const auto show_params = [](const B & obj) {
    for(const auto & p : obj.params()) { std::cout << p << ' '; }
    std::cout << std::endl;
  };
  show_params(D1{});
  show_params(D2{});
}

Но даже если у вас есть непреодолимое стремление создавать объекты именно в динамической памяти, то почему бы не воспользоваться умными указателями из стандартной библиотеки:
int main()
{
  std::unique_ptr<B> d1 = std::make_unique<D1>();
  std::unique_ptr<B> d2 = std::make_unique<D2>();
  ...
}


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

То, что это игрушечный демонстрационный пример ответом не считается. Человек либо говнокодит везде, либо он изначально приучен обходить C++ные грабли.



Могу ошибаться, но вроде как в C++ до сих пор порядок инициализации статических объектов, размещенных в разных единицах трансляции, не определен. Так что если вот здесь:
const params_list D1::my_params_{ "d1_1" };
const params_list D1::params_{ create_params(B::params_, D1::my_params_) };

окажется, что B::params_ и D1::params_ живут в разных единицах трансляции, то в какой-то прекрасный момент вы столкнетесь с тем, что при инициализации D1::params_ присходит обращение к еще не проинициализированному объекту B::params_.
Re[2]: Голые владеющие указатели, правда?
От: ArtDenis Россия  
Дата: 02.04.21 10:11
Оценка:
Здравствуйте, so5team, Вы писали:

S>
S>int main()
S>{
S>  std::unique_ptr<B> d1 = std::make_unique<D1>();
S>  std::unique_ptr<B> d2 = std::make_unique<D2>();
S>  ...
S>}
S>



Раз уж речь зашла о XXI-ом веке, то

int main()
{
  auto d1 = std::make_unique<D1>();
  auto d2 = std::make_unique<D2>();
  ...
}
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re[3]: Голые владеющие указатели, правда?
От: so5team https://stiffstream.com
Дата: 02.04.21 10:14
Оценка:
Здравствуйте, ArtDenis, Вы писали:

AD>Раз уж речь зашла о XXI-ом веке, то


AD>
AD>int main()
AD>{
AD>  auto d1 = std::make_unique<D1>();
AD>  auto d2 = std::make_unique<D2>();
AD>  ...
AD>}
AD>


Не-не-не. Автору принципиально важно было иметь указатели на базовый тип. Поэтому я в своем примере auto не использовал.
Но можно было сделать так:
auto d1 = std::unique_ptr<B>{new D1};
auto d2 = std::unique_ptr<B>{new D2};
Re[4]: Голые владеющие указатели, правда?
От: ArtDenis Россия  
Дата: 02.04.21 10:15
Оценка:
Здравствуйте, so5team, Вы писали:

S>Не-не-не. Автору принципиально важно было иметь указатели на базовый тип. Поэтому я в своем примере auto не использовал.


Точно. Не заметил
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re: Статический список параметров класса
От: ArtDenis Россия  
Дата: 02.04.21 10:56
Оценка:
Здравствуйте, Serg27, Вы писали:

S>Есть иерархия классов. Каждый класс имеет список имен ему нужных параметров, которые потом как-то используются как внутри класса так и извне его. Этот список постоянный для каждого класса. Причем в списке класса потомка присутствует весь список от базового класса. Написал решение. Упрощенный вариант см. ниже. Но можно ли как-то попроще/поизящней?


Путей для упрощения и повышения читаемости очень-очень много. Один из несложных:

struct A
{
    inline static const std::list<std::string> params = { "1", "2" };
};
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re[2]:По теме идеи есть?
От: Serg27  
Дата: 02.04.21 13:16
Оценка:
Здравствуйте, so5team, Вы писали:
S>Простите, что не по теме вашего вопроса. Но.
S>По работе временами приходится заглядывать в дебри чужого кода. И, чем более древний и убогий код, тем чаще там встречается вот такое вот: A * p = new A; Более чем верный маркер того, что дальше будет треш, угар и содомия.

Я даже читать не стал дальше... Там же написано — упрощенный вариант. Про владеющие указатели я знаю лет 20, писал их сам, потом подоспели BOOST и STL. И использую. По теме идеи есть?
Отредактировано 02.04.2021 13:33 Serg27 . Предыдущая версия . Еще …
Отредактировано 02.04.2021 13:22 Serg27 . Предыдущая версия .
Re[3]: Голые владеющие указатели, правда?
От: so5team https://stiffstream.com
Дата: 02.04.21 13:26
Оценка:
Здравствуйте, Serg27, Вы писали:

S>Я даже читать не стал дальше... Там же написано — упрощенный вариант. Про владеющие указатели я знаю лет 20, писал их сам, потом подоспели BOOST и STL. И использую. По теме идеи есть?


А вы таки почитайте, почитайте.
Re[2]: Статический список параметров класса
От: Serg27  
Дата: 02.04.21 13:30
Оценка:
Здравствуйте, ArtDenis, Вы писали:

AD>Путей для упрощения и повышения читаемости очень-очень много. Один из несложных:


AD>
AD>struct A
AD>{
AD>    inline static const std::list<std::string> params = { "1", "2" };
AD>};
AD>


Спасибо. Можно сэкономить строчку. Хотя это поместит детали реализации в заголовочный файл. В моем случае не очень страшно.
Меня больше всего смущает, что придется повторять некоторые куски кода в каждом классе наследнике, а это copy-paste с возможными ошибками. Т.е. надо либо совсем сменить идею (метапрограммирование?), либо сделать что-то более вычурное на шаблонах. И то и другое получается у меня через чур сложно, а код будет жить долго и будет нужно его сопровождать.
Re[3]: Статический список параметров класса
От: ArtDenis Россия  
Дата: 02.04.21 13:47
Оценка:
Здравствуйте, Serg27, Вы писали:

S>Меня больше всего смущает, что придется повторять некоторые куски кода в каждом классе наследнике, а это copy-paste с возможными ошибками. Т.е. надо либо совсем сменить идею (метапрограммирование?), либо сделать что-то более вычурное на шаблонах. И то и другое получается у меня через чур сложно, а код будет жить долго и будет нужно его сопровождать.


Ну можно вообще не трогать объявления классов, а сделать отдельный глобальный объект, который будет позволять регистрировать параметры классов, хранить их в std::[unordered_]map<std::type_info*, params> и выдавать по запросу по typeid
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re[4]: Статический список параметров класса
От: Serg27  
Дата: 02.04.21 13:56
Оценка:
Здравствуйте, ArtDenis, Вы писали:

AD>Ну можно вообще не трогать объявления классов, а сделать отдельный глобальный объект, который будет позволять регистрировать параметры классов, хранить их в std::[unordered_]map<std::type_info*, params> и выдавать по запросу по typeid


Нечто подобное сделано на другом уровне, там регистрируются объекты этих классов. И именно там на этом уровне нужен список параметров, которые используются данным объектом, чтобы при изменении величин параметров "дернуть" именно нужные объекты (ну и еще для некоторых вещей...). Список параметров известен при написании конкретного производного класса и в общем никому больше не интересен (ну кроме собственно "хранилища" этих параметров).
Re[5]: Статический список параметров класса
От: ArtDenis Россия  
Дата: 02.04.21 14:13
Оценка:
Здравствуйте, Serg27, Вы писали:

S>Нечто подобное сделано на другом уровне, там регистрируются объекты этих классов.


Ну так регистрируйте ещё и классы. std::type_info это позволяет
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.