Понимание стоимости связующих

Это заняло целый год, но я прошел через Шаблоны C ++ — Полное руководство Дэвидом Вандевурдом и Николаем М. Йосуттисом, и теперь я застрял в последнем разделе последней главы — связыватели ценностей за последние 3 недели.

Введение в связыватели значений, раздел 22.8 на стр. 457, было достаточно простым для понимания, но примеры в оставшейся части этого раздела были сложными для понимания. Конкретно я не понимаю какие Binder (увидеть функторы / binder1.hpp а также функторы / binder2.hpp а также BinderParams классы (см. функторы / binderparams.hpp) пытаемся добиться. Моя проблема не в синтаксисе шаблона, а в намерениях этих классов.

Как Binder класс, выполняющий привязку? И как BinderParams класс, идентифицирующий (?) параметры? Это то, что мне трудно увидеть / понять.

3

Решение

Это реализация частичное применение, где вы берете функцию (или функтор) и «привязываете» значение к одному из его аргументов, чтобы получить новый функтор, принимающий на один аргумент меньше.

Это чаще всего полезно для объединения генеральный функции с конкретный данные, без необходимости писать дополнительный шаблонный код самостоятельно.

Обратите внимание: вы хотите преобразовать коллекцию, применяя функцию к каждому элементу, в результате чего создается новая коллекция того же размера. Например, std::transform требует унарной функции. Если у вас уже есть функция, которая делает то, что вы хотите, но принимает больше аргументов (например, Kerrek’s AddTwoThings когда вы просто хотите добавить одну и ту же константу к каждому элементу), вы можете:

  • переписать это
  • написать другую функцию для вызова первой с фиксированным аргументом
  • или вы можете привязывать один аргумент к фиксированному значению, получая унарную функцию, используемую std::transform

Для некоторых примеров, показывающих простое использование стандартных эквивалентов C ++ 11 Vandevoorde & Система Josuttis, увидеть удивительно подробный Примеры cppreference.

5

Другие решения

У меня нет книги, и я не пойду и куплю ее, чтобы ответить на этот вопрос (который вы должны переделать, чтобы быть автономным), но я предполагаю, что общая идея примерно такая:

struct AddTwoThings
{
int operator()(int a, int b) const { return a + b; }
};

typedef Binder<AddTwoThings, 0, int> AddThingToSomething;
//                           ^  ^^^
//                           |   |
//      argument position? --+   +-- bound type

AddTwoThings add2;
AddThingToSomething add10(add2, 10);

Сейчас add10(n) такой же как add2(10, n)т.е. 10 + n,

4

Посмотрите на подписи

template< class F, class T >
std::binder1st<F> bind1st( const F& f, const T& x );

template< class F, class T >
std::binder2nd<F> bind2nd( const F& f, const T& x );

То есть функции bind1st а также bind2nd взять функцию и аргумент и вернуть объект функции binder1st а также binder2nd, Вызов этих функциональных объектов вызовет функцию f с его первым или вторым аргументом, оцененным как x,

Раздел, который вы упоминаете в V&J является реализацией этой функциональности. Он был заменен в C ++ 11 более общими std::bind которая имеет подпись

template< class F, class... Args >
/*unspecified*/ bind( F&& f, Args&&... args );

Тип возврата std::bind это то, что вы можете сохранить в auto переменная, но не упоминается явно. Код для реализации настолько сложен, потому что вам нужно сохранить позицию, тип и значение параметра, который вы хотите связать.

3
По вопросам рекламы [email protected]