Форум программистов, компьютерный форум, киберфорум
Наши страницы
C++
Войти
Регистрация
Восстановить пароль
 
tapochka
40 / 40 / 17
Регистрация: 25.04.2014
Сообщений: 499
1

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

14.07.2016, 23:27. Просмотров 429. Ответов 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
Ответы с готовыми решениями:

Какой компонент типа статус бара, подойдет для отображения дробного значения процента?
Подскажите, какой компонент типа статус бара, подойдет для отображения дробного...

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

Обеспечить пропуск расчетов, чтобы избежать деления на ноль
Здравствуйте есть прога, которая вычисляет y=sin(x)/cos(x) в диапазоне...

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

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

13
hoggy
Заблокирован
Эксперт С++
14.07.2016, 23:33 2
Цитата Сообщение от tapochka Посмотреть сообщение
какой паттерн применить в таких случаях чтобы избегать длинных ветвлений в рантайме?
switch case ?
0
tapochka
40 / 40 / 17
Регистрация: 25.04.2014
Сообщений: 499
14.07.2016, 23:35  [ТС] 3
Цитата Сообщение от hoggy Посмотреть сообщение
switch case
ооп-шное что-нибудь
0
Croessmah
++Ͻ
14776 / 8452 / 1605
Регистрация: 27.09.2012
Сообщений: 20,800
Записей в блоге: 2
Завершенные тесты: 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
9014 / 4861 / 1196
Регистрация: 30.01.2014
Сообщений: 7,942
14.07.2016, 23:39 5
tapochka, ООП-шное - это передавать не интовое состояние в класс, а Actor, у которого есть соответствующе определенная операция по работе с vec.
1
hoggy
Заблокирован
Эксперт С++
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 / 17
Регистрация: 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
++Ͻ
14776 / 8452 / 1605
Регистрация: 27.09.2012
Сообщений: 20,800
Записей в блоге: 2
Завершенные тесты: 1
14.07.2016, 23:47 8
Цитата Сообщение от tapochka Посмотреть сообщение
можете плз на коленках набросок кинуть?
В принципе, тоже самое, что и hoggy привел.
Разница в деталях разве что.
0
hoggy
Заблокирован
Эксперт С++
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 / 17
Регистрация: 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
9014 / 4861 / 1196
Регистрация: 30.01.2014
Сообщений: 7,942
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 / 17
Регистрация: 25.04.2014
Сообщений: 499
15.07.2016, 00:21  [ТС] 12
Цитата Сообщение от DrOffset Посмотреть сообщение
Логика такая: если мы все равно задаем ключ операции внешним источником, то может быть сразу саму операцию и передавать извне?
слишком по-уродски получится... выражения трехэтажные получатся

спасибо, мысль понял... жаль только еще более элегантных решений нету...
0
DrOffset
9014 / 4861 / 1196
Регистрация: 30.01.2014
Сообщений: 7,942
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 / 17
Регистрация: 25.04.2014
Сообщений: 499
15.07.2016, 00:57  [ТС] 14
Цитата Сообщение от DrOffset Посмотреть сообщение
Посмотри-ка boost::variant и его static_visitor.
а ведь да... я ж чутка разбирался... спасибо что напомнили

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

Какой паттерн использовать?
Какой паттерн использовать (и использовать ли) в такой ситуации: Существует...

Какой паттерн лучше применить?
Добрый день например в WPF приложении есть 3 Views. Каждая View содержит...

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


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

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Опции темы

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