Разработка общих вариантов алгоритмов - PullRequest
3 голосов
/ 02 марта 2009

Я хочу знать, существует ли шаблон проектирования для указания опций для набора алгоритмов. Я использую C ++. Позвольте мне описать мою проблему. У меня есть набор алгоритмов, и эти алгоритмы имеют разные варианты. Я хочу разработать единую точку доступа к этим алгоритмам. Нечто похожее на шаблон стратегии. Этот одноточечный доступ является классом контроллера, который принимает входные данные как класс общих параметров. В зависимости от параметров будет использован подходящий алгоритм. Я хочу обобщить эти параметры, чтобы я мог расширить алгоритмы и клиента. Спасибо, Amol

Ответы [ 3 ]

7 голосов
/ 02 марта 2009

Часто используемый шаблон - это создание класса политики, который передается вашему классу как тип шаблона, а затем наследуется от частного:

template <typename Policy>
class fancy_algorithm : private Policy {
};

Один известный пример этого - класс std::allocator, который часто наследуется таким образом:

template <typename T, typename Alloc = std::allocator<T> >
class my_container : private Alloc {
public:
    typedef Alloc allocator;

    // It's necessary to make the base class names available explicitly.
    typedef typename allocator::pointer pointer;

    using allocator::construct;
    // …
};
3 голосов
/ 02 марта 2009

Я согласен с Конрадом в отношении основанного на политике дизайна. Я также рекомендую Современный дизайн C ++: применяются общие шаблоны программирования и проектирования . После этой книги ваше видение C ++ навсегда изменится;)

2 голосов
/ 04 марта 2009

Опираясь на Предложение Конрада об использовании типов политики , если ваши алгоритмы требуют параметров во время построения, вы можете справиться с этим чисто, потребовав, чтобы любой класс Policy имел вложенный тип, называемый Params, и затем предоставьте конструктор внутри fancy_algorithm<Policy>, который принимает аргумент этого типа и передает его в содержащийся Policy объект:

template <typename Policy>
class fancy_algorithm : private Policy {
public:
    typedef typename Policy::Params Params;    // Need to redeclare :(

    explicit fancy_algorithm(Params params = Params()) : Policy(params) {}
};

Все соответствующие параметры должны быть упакованы в один объект типа Policy::Params.

Класс Policy всегда создается с одним аргументом типа Policy::Params. Для работы с классами политик, которые (могут) не требовать параметров, предоставьте конструктор по умолчанию (или используйте неявно объявленный) в Params, а не в Policy. Таким образом, используя значение по умолчанию для конструктора fancy_algorithm<Policy>, как указано выше, мы включаем удобную конструкцию по умолчанию для fancy_algorithm<Policy> всякий раз, когда Policy::Params имеет конструктор по умолчанию (т. Е. Когда Policy не требует никаких параметров) , Безопасность не теряется: если у Policy::Params отсутствует конструктор по умолчанию (что указывает на то, что некоторые параметры обязательны ), любая попытка создать объект по умолчанию fancy_algorithm<Policy> не удастся во время компиляции.

Пример:

struct multiply_by_params {
    multiply_by_params(int x /* = 42 */) : _x(x) {}     // See bottom
    int get() const { return _x; }    // Or, just make multiply_by a friend

private:
    int _x;
};

struct multiply_by {
    typedef multiply_by_params Params;
    multiply_by(Params p) : _x(p.get()) { /* Other initialisation */ }

    // Other code implementing the strategy (e.g. an operator()())
    ...

private:
    int _x;
};

fancy_algorithm<multiply_by> a(69); // Always compiles
fancy_algorithm<multiply_by> b;     // Compiles iff /* = 42 */ is uncommented
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...