Войти
ПрограммированиеФорумОбщее

Крестопроблемы

Страницы: 1 2 3 4 Следующая »
#0
(Правка: 19:44) 19:44, 23 янв 2023

Я не большой специалист в трюкачествах на плюсах но нарисовался у меня следующий код:

Есть темплейтный класс:

template<typename T>
class BaseT {
private:
  T m_data;
  //...
public:
  std::string ToString() const {
  //....
  }
};

Есть некая структура с кучей специализированных инстансов:

class Foo {
private:
  BaseT<Bar1> m_bar1;
  BaseT<Bar2> m_bar2;
  BaseT<Bar3> m_bar3;
  BaseT<Bar4> m_bar4;
  BaseT<Bar5> m_bar5;
public:
  std::string ToString() const {
    return m_bar1.ToString() + m_bar2.ToString() + m_bar3.ToString() + m_bar4.ToString() + m_bar5.ToString();
  }
};

Но мне хочется в реализации Foo::ToString писать руками каждое поле. Хочется чтобы оно само, в духе:

  std::string Foo::ToString() {
    std::string res;
    for(const bar& : m_bar_collection) {
      res += bar.ToString();
    }
    return res;
  }

Однако в коллекцию типа std::vector я их сложить не могу, т.к. типы разные. Как быть? На всякий случай: у Bar1, Bar2, Bar3 и т.п. - есть свои деструкторы, они не виртуальные, Bar1, Bar2, Bar3 - не имеют никакого общего предка.

#1
20:05, 23 янв 2023

Унаследуй BaseT от общего базового класса с виртуальным ToString. И сложи в коллекцию указатели на твои разнотипные m_bar.
Можно оставить их как есть, да еще и сложить в коллекцию, а можно от мемберов отказаться, держать их только в коллекции и удалять по счетчикам ссылок. Зависит от того, что еще надо с ними делать, помимо преобразования ToString.

#2
(Правка: 20:18) 20:06, 23 янв 2023

Zab
> Унаследуй BaseT от общего базового класса с виртуальным ToString.
А как это поможет?

MrShoor
> Однако в коллекцию типа std::vector я их сложить не могу, т.к. типы разные. Как быть?

Раз не желаешь иметь общего предка, то никак.

#3
20:29, 23 янв 2023

Ну разве что так https://www.geeksforgeeks.org/how-to-iterate-over-the-elements-of… tdtuple-in-c/
Но ИМХО такой хернёй нет смысла заниматься, лучше унаследовать от общего базового класса.

#4
20:37, 23 янв 2023

Можно еще сделать на темплейтах как на лиспе. Читай Александреску как оно делается. Но я бы не стал такое городить.

#5
20:42, 23 янв 2023

Zab
> И сложи в коллекцию указатели на твои разнотипные m_bar.
Не хочу отдельно указатели отдельно мемберов.

> держать их только в коллекции и удалять по счетчикам ссылок
Вот это было бы замечательно, держать их только в коллекции, только надо без счетчиков, и по возможности без виртуальности. Но даже если виртуального предка от BaseT сделаю, ведь это надо будет еще дополнительно в unique_ptr обернуть каждый объект.

#6
20:45, 23 янв 2023

FROL
> Ну разве что так
> https://www.geeksforgeeks.org/how-to-iterate-over-the-elements-of…
> tdtuple-in-c/
О, а std::tuple прикольно, похоже как раз то что надо! Спасибо.

#7
(Правка: 20:50) 20:48, 23 янв 2023

MrShoor
Можно сделать коллекцию без счетчиков и без виртуальности. Прочитай книгу Александреску. Я не хочу тут расписывать всю эту кухню, оно не на одну сотню страниц. А может ты уже и встречался с подобным ранее, тогда будет легче. Если программировал на лиспе, сразу опознаешь механики, темплейты можно признать лиспоподобным универсальным языком, исполняемым на этапе компиляции. Синтаксически ужасно, но приспособиться можно.

#8
(Правка: 20:52) 20:50, 23 янв 2023

Zab

А вообще нет, вот так как ни странно, работает с виртуальной функцией

+ Показать
#9
21:03, 23 янв 2023

Zab
> Прочитай книгу Александреску.
Ага, спасибо, можно было еще сказать "загугли".

> Я не хочу тут расписывать всю эту кухню
Обычно так отвечают те, кто собственно не может показать пример как это можно сделать. Потому что пример элементарный же.

Der FlugSimulator
> А вообще нет, вот так как ни странно, работает с виртуальной функцией
Так будет работать, но не хочется заводить отдельно вектор указателей.

#10
21:11, 23 янв 2023

MrShoor
Я не люблю такой подход, как у Александреску, он чаще создает проблемы, чем решает их. С какой стати мне его пропагандировать? Ты спросил "можно ли", я ответил "можно" и указал где искать. Захочешь развлечься - найдешь. Как пища для развлечения отлично, но не для практического применения.

А на счет виртуальности ты зря беспокоишься. Да, оно породит дополнительный "лишний" исполняемый постоянно код, может быть неприятно, а в некоторых условиях и неприемлемо. Но ты уже породил ужасные потери, вызвав std::string+std::string+std::string. На их фоне дополнительная виртуальность вообще не видна будет.

#11
(Правка: 21:45) 21:45, 23 янв 2023

Zab
> Но ты уже породил ужасные потери, вызвав std::string+std::string+std::string.
std::string там для примера, у меня там функция сложнее объявлена, и возвращает она не std::string.

FROL
не, std::tuple не подходит, увы. std::get не может же по индексу из переменной читать

#12
22:18, 23 янв 2023

MrShoor
> std::get не может же по индексу из переменной читать
может

#include <iostream>
#include <string>
#include <tuple>
 
int main()
{
    auto t = std::make_tuple("Zab", "MrShoor", "Funtik");
    // index-based access
    std::cout << "(" <<  std::get<1>(t) << ")\n";
}
#13
22:36, 23 янв 2023

Funtik
> может
Не может:

#include <iostream>
#include <string>
#include <tuple>
 
int main()
{
    auto t = std::make_tuple("Zab", "MrShoor", "Funtik");
    for (int i = 0; i < 3; i++)
      std::cout << "(" <<  std::get<i>(t) << ")\n";
}
#14
(Правка: 22:42) 22:38, 23 янв 2023

MrShoor
держи https://godbolt.org/z/6jsMEdaez
если же хочешь через tuple, то смотри в сторону std::apply

Страницы: 1 2 3 4 Следующая »
ПрограммированиеФорумОбщее