Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

C++

Войти
Регистрация
Восстановить пароль
 
tapochka
40 / 40 / 8
Регистрация: 25.04.2014
Сообщений: 499
#1

Какой паттерн подойдет, чтобы избежать длинных ветвлений? - C++

14.07.2016, 23:27. Просмотров 360. Ответов 13
Метки нет (Все метки)

здравствуйте, есть код схематично такой:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class CTest_base {
public:
    CTest_base() : vec() {}
    virtual ~CTest_base() noexcept {}
    //something else
protected:
    std::vector<int> vec;
};
 
class CTest : public CTest_base {
public:
    CTest() : a(0) {}
    ~CTest() noexcept {}
    //something else
    void set() {
        if(a==2)
            vec.shrink_to_fit();
        else if(a==3)
            vec.clear();
        else if(a==4)
            vec.resize(5);
        else 
            vec.emplace_back(0);
    }
    void set_a(int&& a) {
        this->a = std::move(a);
    }
private:
    int a;
};
какой паттерн применить в таких случаях чтобы избегать длинных ветвлений в рантайме? шаблоны не подходят т.к. в рантайме вызывается set_a... observer и template method вроде не подходят... как быть?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
14.07.2016, 23:27
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Какой паттерн подойдет, чтобы избежать длинных ветвлений? (C++):

Какой компонент типа статус бара, подойдет для отображения дробного значения процента? - C++ Builder
Подскажите, какой компонент типа статус бара, подойдет для отображения дробного значения процента? Использую CGauge, но значения туда...

Какой тип лучше всего подойдет для числа? - C++
Есть число 2455903.795232, какой для него лучше всего тип переменной использовать?

Обеспечить пропуск расчетов, чтобы избежать деления на ноль - C++
Здравствуйте есть прога, которая вычисляет y=sin(x)/cos(x) в диапазоне изменения X от 0 с шагом 0,2 Нужно обеспечить пропуск расчетов...

Какой язык программирования лучше всего подойдет начинающему для взаимодействия с веб-сайтами? - C++
Приветствую, форумчане! Какой язык программирования лучше всего подойдет начинающему для взаимодействия с веб-сайтами? Нужно написать...

Какой тип данных лучше подойдет для приложения, которое делит числа int или float? - C++
Ответ написал int Хотя нутром чую, что float

Какой паттерн лучше применить? - ООП и паттерны
Добрый день например в WPF приложении есть 3 Views. Каждая View содержит Control разного типа, пусть это будут кнопки(круглая, квадратная и...

13
hoggy
6652 / 2840 / 486
Регистрация: 15.11.2014
Сообщений: 6,285
Завершенные тесты: 1
14.07.2016, 23:33 #2
Цитата Сообщение от tapochka Посмотреть сообщение
какой паттерн применить в таких случаях чтобы избегать длинных ветвлений в рантайме?
switch case ?
0
tapochka
40 / 40 / 8
Регистрация: 25.04.2014
Сообщений: 499
14.07.2016, 23:35  [ТС] #3
Цитата Сообщение от hoggy Посмотреть сообщение
switch case
ооп-шное что-нибудь
0
Croessmah
Эксперт CЭксперт С++
13419 / 7573 / 855
Регистрация: 27.09.2012
Сообщений: 18,643
Записей в блоге: 3
Завершенные тесты: 1
14.07.2016, 23:38 #4
Цитата Сообщение от tapochka Посмотреть сообщение
как быть?
как вариант - сделать какой-нибудь any с реализацией type erasure,
запихать туда std::function и сделать map/vector/array из any с разными "функциями" внутри.

Еще вариант - map/vector/array с std::function/функциями типа void(std::vector&).
Затем arr[a](vec);. Каждая "функция" вызывает что нужно у вектора.
1
DrOffset
7320 / 4420 / 1001
Регистрация: 30.01.2014
Сообщений: 7,258
14.07.2016, 23:39 #5
tapochka, ООП-шное - это передавать не интовое состояние в класс, а Actor, у которого есть соответствующе определенная операция по работе с vec.
1
hoggy
6652 / 2840 / 486
Регистрация: 15.11.2014
Сообщений: 6,285
Завершенные тесты: 1
14.07.2016, 23:41 #6
Цитата Сообщение от tapochka Посмотреть сообщение
ооп-шное что-нибудь
ну если вам нужен ооп ради ооп, и ради этого вы готовы просадить перфоманс,
замедлив работу без какой либо необходимости,
то можете использовать классический подход:

C++
1
2
3
4
5
std::map<key, std::unique_ptr<ICommand> > commands;
 
...
 
commands[a]->work();
а потом лепить наследников на каждый чих.

кода придется написать больше.
памяти жрать будет больше.
работать будет медленнее.

кстати, белая магия компилятора так же способна в некоторых случаях
представить свитч-кейс в виде ассоциативного массива.
вот только без потерь перфоманса.
1
tapochka
40 / 40 / 8
Регистрация: 25.04.2014
Сообщений: 499
14.07.2016, 23:46  [ТС] #7
Цитата Сообщение от Croessmah Посмотреть сообщение
как вариант - сделать какой-нибудь any с реализацией type erasure,
запихать туда std::function и сделать map/vector/array из any с разными "функциями" внутри.
ну имелось ввиду не только с++... если любой ооп-поддерживаемый язык брать

хотя ваша идея прикольная... да и мастерить никакой any не надо, все же есть в бусте по крайней мере...

Добавлено через 2 минуты
Цитата Сообщение от hoggy Посмотреть сообщение
ну если вам нужен ооп ради ооп, и ради этого вы готовы просадить перфоманс,
замедлив работу без какой либо необходимости,
ну просто в моем случае один метод ну слишком уродский получается через ветвления

Цитата Сообщение от hoggy Посмотреть сообщение
кстати, белая магия компилятора так же способна в некоторых случаях
представить свитч-кейс в виде ассоциативного массива.
да читал вроде всегда так компилятор поступает... не проверял правда

Добавлено через 1 минуту
Цитата Сообщение от DrOffset Посмотреть сообщение
tapochka, ООП-шное - это передавать не интовое состояние в класс, а Actor, у которого есть соответствующе определенная операция по работе с vec.
можете плз на коленках набросок кинуть?
0
Croessmah
Эксперт CЭксперт С++
13419 / 7573 / 855
Регистрация: 27.09.2012
Сообщений: 18,643
Записей в блоге: 3
Завершенные тесты: 1
14.07.2016, 23:47 #8
Цитата Сообщение от tapochka Посмотреть сообщение
можете плз на коленках набросок кинуть?
В принципе, тоже самое, что и hoggy привел.
Разница в деталях разве что.
0
hoggy
6652 / 2840 / 486
Регистрация: 15.11.2014
Сообщений: 6,285
Завершенные тесты: 1
14.07.2016, 23:49 #9
Цитата Сообщение от tapochka Посмотреть сообщение
ну просто в моем случае один метод ну слишком уродский получается через ветвления
если ключи идут строго друг за другом,
то можно сделать обычный вектор акторов std::function

C++
1
2
3
4
std::vector< std::function<void()> > actors;
 
actors.emplace_back(  [&vec](){ vec.shrink_to_fit();  }  );
actors.at(a)();
1
tapochka
40 / 40 / 8
Регистрация: 25.04.2014
Сообщений: 499
14.07.2016, 23:57  [ТС] #10
вот думал что-то типа tag-dispatching... прикрутить бы(из инета код)
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
namespace std {
  struct input_iterator_tag { };
  struct bidirectional_iterator_tag : input_iterator_tag { };
  struct random_access_iterator_tag : bidirectional_iterator_tag { };
 
  namespace detail {
    template <class InputIterator, class Distance>
    void advance_dispatch(InputIterator& i, Distance n, input_iterator_tag) {
      while (n--) ++i;
    }
 
    template <class BidirectionalIterator, class Distance>
    void advance_dispatch(BidirectionalIterator& i, Distance n, 
       bidirectional_iterator_tag) {
      if (n >= 0)
        while (n--) ++i;
      else
        while (n++) --i;
    }
 
    template <class RandomAccessIterator, class Distance>
    void advance_dispatch(RandomAccessIterator& i, Distance n, 
       random_access_iterator_tag) {
      i += n;
    }
  }
 
  template <class InputIterator, class Distance>
  void advance(InputIterator& i, Distance n) {
    typename iterator_traits<InputIterator>::iterator_category category;
    detail::advance_dispatch(i, n, category);
  }
}
Добавлено через 2 минуты
в моем случае просто идет работа с view, т.е. быстродействие совсем не обязательно... можно экспериментировать со свистелками-перделками
0
DrOffset
7320 / 4420 / 1001
Регистрация: 30.01.2014
Сообщений: 7,258
15.07.2016, 00:09 #11
Цитата Сообщение от tapochka Посмотреть сообщение
можете плз на коленках набросок кинуть?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class CTest
    : public CTest_base
{
public:
    CTest() : a() {}
    ~CTest() noexcept {}
    //something else
    void set()
    {
        a(vec);
    }
    template <typename Actor>
    void set_a(Actor && ac)
    {
        a = std::move(ac);
    }
private:
    std::function<void(std::vector<int> &)> a;
};
Логика такая: если мы все равно задаем ключ операции внешним источником, то может быть сразу саму операцию и передавать извне?
1
tapochka
40 / 40 / 8
Регистрация: 25.04.2014
Сообщений: 499
15.07.2016, 00:21  [ТС] #12
Цитата Сообщение от DrOffset Посмотреть сообщение
Логика такая: если мы все равно задаем ключ операции внешним источником, то может быть сразу саму операцию и передавать извне?
слишком по-уродски получится... выражения трехэтажные получатся

спасибо, мысль понял... жаль только еще более элегантных решений нету...
0
DrOffset
7320 / 4420 / 1001
Регистрация: 30.01.2014
Сообщений: 7,258
15.07.2016, 00:32 #13
Ну или (если уж от интового ключа никак не избавиться) как-то так:
В принципе и без std::function можно обойтись.
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class CTest
    : public CTest_base
{
public:
    CTest() : a() {}
    ~CTest() noexcept {}
    //something else
    void set()
    {
        a(vec);
    }
    void set_a(int key)
    {
        static void ( * op[])(std::vector<int> &) =
        {
             [](std::vector<int> & vec) {  vec.emplace_back(0); }
           , [](std::vector<int> & vec) {  vec.resize(5); }
           , [](std::vector<int> & vec) {  vec.clear(); }
           , [](std::vector<int> & vec) {  vec.shrink_to_fit(); }
        };
        a = op[key];
    }
 
private:
    void(* a)(std::vector<int> &);
};


Добавлено через 7 минут
Цитата Сообщение от tapochka Посмотреть сообщение
жаль только еще более элегантных решений нету
Да есть. Просто задача непонятная, допуски на задачу непонятные.
Универсального решения - да, нету. Но это всем известно.

Насчет:
Цитата Сообщение от tapochka Посмотреть сообщение
вот думал что-то типа tag-dispatching.
Посмотри-ка boost::variant и его static_visitor.
И вот сюда глянь: https://stackoverflow.com/questions/...late-functions
1
tapochka
40 / 40 / 8
Регистрация: 25.04.2014
Сообщений: 499
15.07.2016, 00:57  [ТС] #14
Цитата Сообщение от DrOffset Посмотреть сообщение
Посмотри-ка boost::variant и его static_visitor.
а ведь да... я ж чутка разбирался... спасибо что напомнили

Добавлено через 18 минут
вот по этой статье разбирался, может кому пригодится
[вырезано]
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
15.07.2016, 00:57
Привет! Вот еще темы с ответами:

На какой паттерн заменить switch? - ООП и паттерны
Ситуация следующая: есть перечисление (5 элементов Type1 = 6, Type2 = 12....). Их интовое значение в итоге повлияет на размерность матрицы....

Посоветуйте, какой паттерн можно применить? - ООП и паттерны
Ситуация следующая. Есть класс с набором методов, от него наследуется 3 класса, у каждого класса добавляются дополнительные поля и...

.NET 4.x Какой наиболее правильный паттерн при работе с SQLite - C#
Что есть: Entity Framework - набор классов для работы с базой данных WPF - забинденные Listview ... DataGrid ... Combobox к свойствам...

Какой Linux подойдет - Linux
Подскажите какой Linux подойдет на такое железо ОЗУ - 1536 МБ DDR Проц - Intel Celeron 1.9 Ггц Видео - интегрненая HDD - 150 GB


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
14
Yandex
Объявления
15.07.2016, 00:57
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru