Это заняло целый год, но я прошел через Шаблоны C ++ — Полное руководство Дэвидом Вандевурдом и Николаем М. Йосуттисом, и теперь я застрял в последнем разделе последней главы — связыватели ценностей за последние 3 недели.
Введение в связыватели значений, раздел 22.8 на стр. 457, было достаточно простым для понимания, но примеры в оставшейся части этого раздела были сложными для понимания. Конкретно я не понимаю какие Binder
(увидеть функторы / binder1.hpp а также функторы / binder2.hpp а также BinderParams
классы (см. функторы / binderparams.hpp) пытаемся добиться. Моя проблема не в синтаксисе шаблона, а в намерениях этих классов.
Как Binder
класс, выполняющий привязку? И как BinderParams
класс, идентифицирующий (?) параметры? Это то, что мне трудно увидеть / понять.
Это реализация частичное применение, где вы берете функцию (или функтор) и «привязываете» значение к одному из его аргументов, чтобы получить новый функтор, принимающий на один аргумент меньше.
Это чаще всего полезно для объединения генеральный функции с конкретный данные, без необходимости писать дополнительный шаблонный код самостоятельно.
Обратите внимание: вы хотите преобразовать коллекцию, применяя функцию к каждому элементу, в результате чего создается новая коллекция того же размера. Например, std::transform
требует унарной функции. Если у вас уже есть функция, которая делает то, что вы хотите, но принимает больше аргументов (например, Kerrek’s AddTwoThings
когда вы просто хотите добавить одну и ту же константу к каждому элементу), вы можете:
std::transform
Для некоторых примеров, показывающих простое использование стандартных эквивалентов C ++ 11 Vandevoorde & Система Josuttis, увидеть удивительно подробный Примеры cppreference.
У меня нет книги, и я не пойду и куплю ее, чтобы ответить на этот вопрос (который вы должны переделать, чтобы быть автономным), но я предполагаю, что общая идея примерно такая:
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
,
Посмотрите на подписи
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
переменная, но не упоминается явно. Код для реализации настолько сложен, потому что вам нужно сохранить позицию, тип и значение параметра, который вы хотите связать.