Russian Qt Forum

Программирование => С/C++ => Тема начата: kuzulis от Сентябрь 03, 2016, 15:21



Название: [шаблоны] Посоветуйте, можно ли улучшить код
Отправлено: kuzulis от Сентябрь 03, 2016, 15:21
Всем доброго времени.

Суть: приложение имеет много классов-менеджеров, которые делают однообразную работу:
добавляют, удаляют, подсчитывают кол-во каких-то своих элементов и прочую работу.

Так вот, хотелось бы не плодить кучу реализаций этих менеджеров (не дублировать код
в каждом менеджере по добавлению, удалению элементов и пр.), а как-бы все отшаблонить.

Я не спец-по-шаблонам, получилось как-то так main.cpp:

Код
C++ (Qt)
#include <QCoreApplication>
#include <QList>
#include <QSharedPointer>
#include <QDebug>
 
template <class Manager, typename Element>
class ElementManager : public QObject
{
public:
   explicit ElementManager();
   virtual ~ElementManager();
 
   void addElement(const Element &element);
   void removeElement(const Element &element);
 
   static Manager *instance();
 
private:
   QList<Element> m_elements;
   static Manager *m_instance;
};
 
template <class Manager, typename Element>
Manager *ElementManager<Manager, Element>::m_instance = nullptr;
 
template <class Manager, typename Element>
ElementManager<Manager, Element>::ElementManager()
{
   m_instance = static_cast <Manager*> (this);
}
 
template <class Manager, typename Element>
ElementManager<Manager, Element>::~ElementManager()
{
   m_instance = nullptr;
}
 
template <class Manager, typename Element>
void ElementManager<Manager, Element>::addElement(const Element &element)
{
   m_elements.append(element);
}
 
template <class Manager, typename Element>
void ElementManager<Manager, Element>::removeElement(const Element &element)
{
   m_elements.removeOne(element);
}
 
template <class Manager, typename Element>
Manager *ElementManager<Manager, Element>::instance()
{
   return m_instance;
}
 
class Foo : public QObject
{
   Q_OBJECT
public:
   typedef QSharedPointer<Foo> Ptr;
   explicit Foo() = default;
};
 
class FooManager: public ElementManager<FooManager, Foo::Ptr>
{
   Q_OBJECT
public:
   explicit FooManager() = default;
 
   void do_something() {
       qDebug() << "FooManager: do something";
       emit fooSomething();
   }
 
signals:
   void fooSomething();
};
 
class Bar : public QObject
{
   Q_OBJECT
public:
   typedef QSharedPointer<Bar> Ptr;
   explicit Bar() = default;
};
 
class BarManager: public ElementManager<BarManager, Bar::Ptr>
{
   Q_OBJECT
public:
   explicit BarManager() = default;
 
   void do_something() {
       qDebug() << "BarManager: do something";
       emit barSomething();
   }
 
signals:
   void barSomething();
};
 
int main(int argc, char *argv[])
{
   QCoreApplication a(argc, argv);
 
   {
       new FooManager;
       auto p = FooManager::instance();
       p->do_something();
   }
 
   {
       new BarManager;
       auto p = BarManager::instance();
       p->do_something();
   }
 
   return a.exec();
}
 
#include "main.moc"
 

Это нормально, или можно как-то улучшить? :)

UPD: Еще бы было бы хорошо, если бы можно было добавить сигналы типа elementAdded(Removed) в базовый шаблонный класс ElementManager, но, кажется это невозможно с шаблонами в Qt.


Название: Re: [шаблоны] Посоветуйте, можно ли улучшить код
Отправлено: Igors от Сентябрь 03, 2016, 16:28
Неясен ф-ционал самого менеджера. Ну добавили в него объект - и что? Если планируете что-то делать со всеми объектами в менеджере то он просто "контейнер". Логично чтобы клиенты запрашивали у менеджера объект, но никаких намеков на get() не видно.

Удаление по константной ссылке как-то конфузит - у клиента объект имеется, хз сколько этот объект будет жить, а равный ему объект почему-то удаляем из менеджера. Что таким образом хотим получить?

Зачем нужен первый аргумент темплейта (Manager) - не знаю, по-моему этот наворот ни к чему.

Если в качестве объектов планируются шаред пойнтеры, то лучше это в темплейте и объявить, т.е. "только шаред", смешивать толку не будет


Название: Re: [шаблоны] Посоветуйте, можно ли улучшить код
Отправлено: kuzulis от Сентябрь 03, 2016, 21:45
Цитировать
Неясен ф-ционал самого менеджера. Ну добавили в него объект - и что?
но никаких намеков на get() не видно.

Ну, это ж просто пример. естественно, есть там всякие get и прочее. не буду же я рисовать здесь всю подноготную.

Цитировать
Удаление по константной ссылке как-то конфузит - у клиента объект имеется, хз сколько этот объект будет жить

Это просто пример. На самом деле каждый элемент имеет уникальный идентификатор,
 и удаляться оно будет по идентификаторам а не по шаред пойнтерам.

Код
C++ (Qt)
void removeElement(const Id &id);
 

Цитировать
Зачем нужен первый аргумент темплейта (Manager) - не знаю, по-моему этот наворот ни к чему.

А без него работать не будет,например это не будет:

Код
C++ (Qt)
p->do_something();
 

Вот для этого я и задал вопрос. Может можно как-то это завернуть еще в template template... но я хз.
То до чего я додумался - это определить два параметра шаблона.

Цитировать
Если в качестве объектов планируются шаред пойнтеры, то лучше это в темплейте и объявить, т.е. "только шаред", смешивать толку не будет

Могут быть любые объекты.


Название: Re: [шаблоны] Посоветуйте, можно ли улучшить код
Отправлено: kuzulis от Сентябрь 03, 2016, 22:07
Вот, немного подрихтовал:

Код
C++ (Qt)
#include <QCoreApplication>
#include <QList>
#include <QSharedPointer>
#include <QDebug>
 
#include <algorithm>
 
class IManager : public QObject
{
   Q_OBJECT
signals:
   void elementAdded(const QString &elementId);
   void elementRemoved(const QString &elementId);
 
protected:
   void emitElementAdded(const QString &elementId) {
       emit elementAdded(elementId);
   }
   void emitElementRemoved(const QString &elementId) {
       emit elementRemoved(elementId);
   }
};
 
class IElement : public QObject
{
public:
   explicit IElement(const QString &elementId)
       : m_elementId(elementId)
   {
   }
 
   QString id() const {
       return m_elementId;
   }
 
private:
   QString m_elementId;
};
 
template <class Manager, typename Element>
class ElementManager : public IManager
{
public:
   explicit ElementManager();
   virtual ~ElementManager();
 
   Element element(const QString &elementId) const;
   void addElement(const Element &element);
   void removeElement(const QString &elementId);
 
   static Manager *instance();
 
private:
   QList<Element> m_elements;
   static Manager *m_instance;
};
 
template <class Manager, typename Element>
Manager *ElementManager<Manager, Element>::m_instance = nullptr;
 
template <class Manager, typename Element>
ElementManager<Manager, Element>::ElementManager()
{
   m_instance = static_cast <Manager*> (this);
}
 
template <class Manager, typename Element>
ElementManager<Manager, Element>::~ElementManager()
{
   m_instance = nullptr;
}
 
template <class Manager, typename Element>
Element ElementManager<Manager, Element>::element(const QString &elementId) const
{
   const auto end = m_elements.cend();
   const auto it = std::find_if(m_elements.cbegin(), end, [elementId](Element element) {
           return element->id() == elementId;
   });
 
   return (it == end) ? Element() : *it;
}
 
template <class Manager, typename Element>
void ElementManager<Manager, Element>::addElement(const Element &element)
{
   m_elements.append(element);
   emitElementAdded(element->id());
}
 
template <class Manager, typename Element>
void ElementManager<Manager, Element>::removeElement(const QString &elementId)
{
   auto e = element(elementId);
   if (e) {
       m_elements.removeOne(e);
       emitElementRemoved(e->id());
   }
}
 
template <class Manager, typename Element>
Manager *ElementManager<Manager, Element>::instance()
{
   return m_instance;
}
 
class Foo : public IElement
{
   Q_OBJECT
public:
   typedef QSharedPointer<Foo> Ptr;
   explicit Foo(const QString &id)
       : IElement(id)
   {
   }
};
 
class FooManager: public ElementManager<FooManager, Foo::Ptr>
{
   Q_OBJECT
public:
   explicit FooManager() = default;
 
   void do_something() {
       qDebug() << "FooManager: do something";
       emit fooSomething();
   }
 
signals:
   void fooSomething();
};
 
class Bar : public IElement
{
   Q_OBJECT
public:
   typedef QSharedPointer<Bar> Ptr;
   explicit Bar()
       : IElement(QLatin1String("bar.id"))
   {
   }
};
 
class BarManager: public ElementManager<BarManager, Bar::Ptr>
{
   Q_OBJECT
public:
   explicit BarManager() = default;
 
   void do_something() {
       qDebug() << "BarManager: do something";
       emit barSomething();
   }
 
signals:
   void barSomething();
};
 
int main(int argc, char *argv[])
{
   QCoreApplication a(argc, argv);
 
   {
       new FooManager;
       auto p = FooManager::instance();
 
       Foo::Ptr foo(new Foo(QLatin1String("foo1.id")));
       p->addElement(foo);
       p->removeElement(QLatin1String("foo1.id"));
       p->do_something();
   }
 
   {
       new BarManager;
       auto p = BarManager::instance();
       p->do_something();
   }
 
   return a.exec();
}
 
#include "main.moc"
 


Название: Re: [шаблоны] Посоветуйте, можно ли улучшить код
Отправлено: Igors от Сентябрь 04, 2016, 10:10
Вот для этого я и задал вопрос. Может можно как-то это завернуть еще в template template... но я хз.
То до чего я додумался - это определить два параметра шаблона.
Ага, теперь понял. Насколько я знаю (любителем template никогда не был), то что Вы сделали вполне нормально и называется traits. Можно и без него
Код
C++ (Qt)
class FooManager: public ElementManager<Foo::Ptr>
{
..
 FooManager * instance( void ) { return static_cast<FooManager *> (m_instance); }


Название: Re: [шаблоны] Посоветуйте, можно ли улучшить код
Отправлено: kuzulis от Сентябрь 04, 2016, 10:58
Да, можно и без него, но тогда придётся в каждом экземпляре менеджера писать реализацию получения инстанса и прочие лишние телодвижения.



Название: Re: [шаблоны] Посоветуйте, можно ли улучшить код
Отправлено: Igors от Сентябрь 04, 2016, 14:27
Да, можно и без него, но тогда придётся в каждом экземпляре менеджера писать реализацию получения инстанса и прочие лишние телодвижения.
Если появятся "прочие", пока их не видно


Название: Re: [шаблоны] Посоветуйте, можно ли улучшить код
Отправлено: kuzulis от Сентябрь 04, 2016, 21:03
Да, с дополнительным параметром "Manager" появляются проблемы при получении инстанса, если сам объект менеджера был создан в одном модуле (шаред библиотеке), а статический метод instance() вызван из другого модуля (другой шаред библиотеки). В этом случае почему-то возвращается нулевой инстанс... o_O (хотя сам объект создается раньше чем дегается его метод инстанс).

Так что я пока подзабил и сделал как раньше с одним шаблонным параметром "Element".  :)



Название: Re: [шаблоны] Посоветуйте, можно ли улучшить код
Отправлено: Igors от Сентябрь 05, 2016, 08:36
(хотя сам объект создается раньше чем дегается его метод инстанс).
Присвоение m_instance происходит в конструкторе базового класса, т.е. когда сам Manager еще не сконструирован. Может и будет работать, но как-то это нездорово/чревато


Название: Re: [шаблоны] Посоветуйте, можно ли улучшить код
Отправлено: panAlexey от Сентябрь 07, 2016, 23:51
Да, можно и без него, но тогда придётся в каждом экземпляре менеджера писать реализацию получения инстанса и прочие лишние телодвижения.
фабрика?
хотя голова уже не варит.


Название: Re: [шаблоны] Посоветуйте, можно ли улучшить код
Отправлено: __Heaven__ от Сентябрь 12, 2016, 14:17
kuzulis, быть может в модуле сделать функции, которые будут возвращать указатель на статику?


Название: Re: [шаблоны] Посоветуйте, можно ли улучшить код
Отправлено: __Heaven__ от Сентябрь 12, 2016, 15:57
kuzulis, взгляните на это:
Код
C++ (Qt)
#include <QObject>
#include <QVector>
#include <QtDebug>
#include <memory>
 
class IManager{
public:
   virtual void doSomething() = 0;
   virtual ~IManager(){
   }
};
 
class AbstractManager: public QObject, public IManager{
   Q_OBJECT
 
signals:
   void elementAdded(const QString &elementId);
   void elementRemoved(const QString &elementId);
};
 
 
template<typename T>
struct Element{
   QString id;
   T value;
};
 
 
template<class T>
class ElementManager: public AbstractManager{
   using ElementType = Element<T>;
   using Container = QVector<ElementType>;
public:
   ElementManager(){
       if (instance_){
           qCritical() << "Overwritting ElementManager global instance";
       }
 
       instance_ = this;
   }
 
   virtual ~ElementManager() override {
       instance_ = nullptr;
   }
 
   void addElement(const ElementType &element){
       elements_ << element;
       emit elementAdded(element.id);
   }
 
   void removeElement(const QString &id){
       typename Container::iterator it = find(id);
       elements_.erase(it);
       emit elementRemoved(id);
   }
 
   ElementType element(const QString &id) const{
       return *find(id);
   }
 
   static IManager *instance(){
       return instance_;
   }
 
private:
   typename Container::iterator find(const QString &id){
       for (typename Container::iterator it = elements_.begin(), end = elements_.end(); it != end; ++it){
           if (it->id == id){
               return it;
           }
       }
       return  elements_.end();
   }
 
private:
   static IManager *instance_;
   Container elements_;
};
 
template<typename T>
IManager *ElementManager<T>::instance_ = nullptr;
 
template<typename T>
IManager *instance(){
   return ElementManager<T>::instance();
}
 
class IntManager: public ElementManager<int>{
public:
   IntManager(){
   }
   virtual ~IntManager() override{
   }
 
   virtual void doSomething() override{
       qDebug() << "IntManager doing something";
   }
};
 
class StringManager: public ElementManager<QString>{
public:
   StringManager(){
   }
   virtual ~StringManager() override{
   }
 
   virtual void doSomething() override{
       qDebug() << "StringManager doing something";
   }
};
 
 
int main()
{
   using IntElement = Element<int>;
   using StringElement = Element<QString>;
 
   IntElement intElement;
   intElement.id = "int.id";
   intElement.value = 7;
 
   IntManager intManager;
   QObject::connect(&intManager, &IntManager::elementAdded, [=](const QString &id){qDebug() << "Element with id" << id << "added to int manager";});
   QObject::connect(&intManager, &IntManager::elementRemoved, [=](const QString &id){qDebug() << "Element with id" << id << "removed from int manager";});
   intManager.addElement(intElement);
 
   StringElement stringElement;
   stringElement.id = "string.id";
   stringElement.value = "Qt";
 
   StringManager stringManager;
   stringManager.addElement(stringElement);
 
   std::array<IManager *, 2> intances{{
       instance<int>(),
       instance<QString>()
   }};
 
   for (IManager *instance: intances){
       instance->doSomething();
   }
 
 
   return 0;
}
 
#include "main.moc"
 

Я пытался оформить instance_ как std::unique_ptr, но тогда происходил вылет, видать, нельзя делать unique статичным.


Название: Re: [шаблоны] Посоветуйте, можно ли улучшить код
Отправлено: kuzulis от Сентябрь 12, 2016, 19:30
Кстати, а разве оно должно компилиться? Ведь с "emit elementRemoved(id);" в шаблонном классе оно не должно компилиться. Не?


Название: Re: [шаблоны] Посоветуйте, можно ли улучшить код
Отправлено: __Heaven__ от Сентябрь 12, 2016, 19:36
Я копипастил из QtCreator, код работает.


Название: Re: [шаблоны] Посоветуйте, можно ли улучшить код
Отправлено: __Heaven__ от Сентябрь 12, 2016, 19:54
Код
C++ (Qt)
ElementType element(const QString &id) const{
       return *find(id);
   }
Тут проверку забыл написать


Название: Re: [шаблоны] Посоветуйте, можно ли улучшить код
Отправлено: kuzulis от Сентябрь 13, 2016, 09:48
Да, спс, точно, компилится (по крайней мере на винде)..


Название: Re: [шаблоны] Посоветуйте, можно ли улучшить код
Отправлено: __Heaven__ от Сентябрь 13, 2016, 09:56
Под g++ и clang тоже компилится


Название: Re: [шаблоны] Посоветуйте, можно ли улучшить код
Отправлено: Igors от Сентябрь 13, 2016, 12:03
Код
C++ (Qt)
class IManager{
..
class AbstractManager: public QObject, public IManager{
..
template<class T>
class ElementManager: public AbstractManager{
..
 
Как-то дороговато достигается пресловутая "общность". Конечно в этих 3 классах нет ничего сложного, но это все-таки уже 3 класса.

И виртуальный doSomething обычно не устраивает, это дела конкретной инстансы


Название: Re: [шаблоны] Посоветуйте, можно ли улучшить код
Отправлено: __Heaven__ от Сентябрь 13, 2016, 13:12
В чём дороговизна? Количество классов? А чем это мешает?
Например, в использовании QTreeView разве мешает его наследование от QTreeView, QAbstractItemView, QAbstractScrollArea, QFrame, QWidget, QObject, QPaintDevice?

Цитировать
И виртуальный doSomething обычно не устраивает, это дела конкретной инстансы
Я не понял, что здесь написано


Название: Re: [шаблоны] Посоветуйте, можно ли улучшить код
Отправлено: Igors от Сентябрь 13, 2016, 14:13
В чём дороговизна? Количество классов? А чем это мешает?
Например, в использовании QTreeView разве мешает его наследование от QTreeView, QAbstractItemView, QAbstractScrollArea, QFrame, QWidget, QObject, QPaintDevice?
А могут ли Ваши IManager, AbstractManager, ElementManager претендовать на ту же капитальность/фундаментальность? Оправдывают ли они время что нужно затратить на знакомство с ними?

Цитировать
И виртуальный doSomething обычно не устраивает, это дела конкретной инстансы
Я не понял, что здесь написано
Начиная с какого-то момента менеджеры обычно "расходятся", т.е. обзаводятся своими методами которые имеют смысл только для данной инстансы. Напр StringManager может иметь something для поиска в QString, но для IntManager это лишено смысла. А виртуалом можно поддержать только общую для всех операцию


Название: Re: [шаблоны] Посоветуйте, можно ли улучшить код
Отправлено: __Heaven__ от Сентябрь 13, 2016, 15:09
Цитировать
Начиная с какого-то момента менеджеры обычно "расходятся", т.е. обзаводятся своими методами которые имеют смысл только для данной инстансы
Пускай расходятся, я не против. Функционал будет расширяться невиртуальными методами.
Цитировать
А виртуалом можно поддержать только общую для всех операцию
Виртуал здесь выделен по той причине, что из шапки видно, что ТС хочет иметь некий метод do_Something в каждом экземпляре менеджера. Также видно, что он хочет возвращать указатели на менеджеров. Я предположил, что возможно он, захочет ещё держать менеджеров в неком контейнере и в цикле вызывать у каждого do_Something.

Цитировать
Оправдывают ли они время что нужно затратить на знакомство с ними?
Вы с QPaintDevice знакомились от и до перед тем как использовать QWidget? Также если я хочу досконально знакомиться с классом, то я быстрее познакомлюсь с классом в 50 строк, чем с монстром в 1000.

Цитировать
капитальность/фундаментальность
Опять не понимаю.


Название: Re: [шаблоны] Посоветуйте, можно ли улучшить код
Отправлено: Igors от Сентябрь 13, 2016, 16:03
Цитировать
капитальность/фундаментальность
Опять не понимаю.
Знакомиться с  QTreeView, QAbstractItemView, QAbstractScrollArea, QFrame, QWidget, QObject, QPaintDevice все равно так или иначе придется, причем это можно делать постепенно. почитывая букварь от случая к случаю. Понадобилось что-то - освоил, а "надобится" постоянно.

А вот с самопальными классами ситуация другая. Это совсем не претензия к Вам лично, ситуация очень типовая. Да, часто можно добиться желаемого, но.. стоит ли оно того? Достаточно ли много достигается 3-мя классами? Может можно было обойтись одним? Не исключено что вообще никакие template здесь не нужны - тупо продублить код для 10 менеджеров. Пока общего ф-ционала с гулькин нос (add и delete) - почему нет? Тут часто говорят "а если.." - да, но часто никаких расширений не происходит (ну вот не растет проект в эту степь), и излишняя/дутая общность оседает мертвым грузом


Название: Re: [шаблоны] Посоветуйте, можно ли улучшить код
Отправлено: __Heaven__ от Сентябрь 13, 2016, 16:53
Цитировать
тупо продублить код для 10 менеджеров
Потом тупо исправить ошибку в 9 из них и тупо забыть исправить в 10. Затем понять, что надо немножко расширить функционал и снова тупо копипастить. А потом мы в менеджере №3 захотим метод сортировки наоборот, а в менеджере 8 возможность общаться с себе подобными. И, конечно, будет куда проще разобраться в этих 10 классах, чем в одном шаблоне.

Цитировать
с самопальными классами ситуация другая
Чем же она другая? Никто не запрещает пользоваться классом ElementManager не зная внутреннего строения AbstractManager. Точно также, никто не запрещает постепенно осваивать AbstractManager.

Цитировать
Может можно было обойтись одним
Конечно можно. А ещё можно обойтись процедурным программированием в едином main.cpp или ассемблером.
Повторю, что на мой взгляд, понять устройство маленького класса значительно проще. Помимо этого здесь есть преимущество в скорости компиляции. Не всегда требуется инклудом тащить толстый класс (а может и не один). Достаточно взять интерфейс и через него вызывать необходимые виртуальные методы. Мне кажется, что вам эти преимущества уже не один раз разъясняли и вы вновь занимаетесь флудом в сторонней теме.

Цитировать
Пока общего ф-ционала с гулькин нос (add и delete) - почему нет?
Потому что ТС писал
Цитировать
не буду же я рисовать здесь всю подноготную
Наверняка класс будет претерпевать расширение.

Цитировать
излишняя/дутая общность оседает мертвым грузом
А про классы без использования шаблонов вы случаем не скажете того же самого?

2 kuzulis, а вы не рассматривали вариант использования QMap<IdType, ValueType> ?


Название: Re: [шаблоны] Посоветуйте, можно ли улучшить код
Отправлено: kuzulis от Сентябрь 13, 2016, 18:10
Цитировать
2 kuzulis, а вы не рассматривали вариант использования QMap<IdType, ValueType> ?

Не, сейчас все устраивает.. правда я слепил IManager + AbstractManager в один класс... т.о. у меня только две реализации: QObject-овая и шаблонная..  


Название: Re: [шаблоны] Посоветуйте, можно ли улучшить код
Отправлено: Igors от Сентябрь 14, 2016, 06:51
Потом тупо исправить ошибку в 9 из них и тупо забыть исправить в 10. Затем понять, что надо немножко расширить функционал и снова тупо копипастить.
Да, может быть и так

А потом мы в менеджере №3 захотим метод сортировки наоборот, а в менеджере 8 возможность общаться с себе подобными. И, конечно, будет куда проще разобраться в этих 10 классах, чем в одном шаблоне.
А здесь неясно. Если 10 совершенно независимых классов - у меня никаких проблем с сортировкой наоборот в менеджере №3. А вот если укладывать их в общую конструкцию - придется пыхтеть с обобщением.

И, конечно, будет куда проще разобраться в этих 10 классах, чем в одном шаблоне.
Не исключено что и легче. Напр можно записать
Код
C++ (Qt)
manager.addMyObject();
// вместо безликого
manager.addElement();
 
И это может оказаться лучше (или приятнее) экономии с template

Чем же она другая? Никто не запрещает пользоваться классом ElementManager не зная внутреннего строения AbstractManager. Точно также, никто не запрещает постепенно осваивать AbstractManager.
Ну это вряд ли  :)

Достаточно взять интерфейс и через него вызывать необходимые виртуальные методы. Мне кажется, что вам эти преимущества уже не один раз разъясняли и вы вновь занимаетесь флудом в сторонней теме.
Не кипятитесь :) Я же не говорю что предложенное Вами плохо. Просто не все так однозначно, есть масса переходов и других цветов кроме "черного и белого". Если менеджеры хранят разные классы, то очень может быть что ничего "особо общего" у них и не найдется


Название: Re: [шаблоны] Посоветуйте, можно ли улучшить код
Отправлено: __Heaven__ от Сентябрь 14, 2016, 07:37
А потом мы в менеджере №3 захотим метод сортировки наоборот, а в менеджере 8 возможность общаться с себе подобными. И, конечно, будет куда проще разобраться в этих 10 классах, чем в одном шаблоне.
А здесь неясно. Если 10 совершенно независимых классов - у меня никаких проблем с сортировкой наоборот в менеджере №3. А вот если укладывать их в общую конструкцию - придется пыхтеть с обобщением.
Код
C++ (Qt)
class DescSortIntManager: public ElementManager<int>{
   void sort();
}
 


Название: Re: [шаблоны] Посоветуйте, можно ли улучшить код
Отправлено: Akon от Сентябрь 22, 2016, 11:44
ИМХО, видится такая реализация:

- менеджер - елементы: независимо от типов обоих, уже есть что-то общее (добавить/удалить и т.п.), поэтому делаются базовые нешаблонные классы Manager, Element. В этих классах декларируются сигналы added(Element*)/removed(Element*) и т.п. Естественно, для обеспечения полиморфизма здесь используются только указатели Manager*, Element* (или смарт-указатели).

- далее для типобезопасности используются тонкие шаблонные обертки, выполняющие downcast.

В результате, нет "раздутия" кода из-за шаблонов, и есть типобезопасность.