vector<string*> pvec;
function<bool (const string*)> fp = &string::empty;
// fp получает указатель на string и использует оператор ->* для вызова
// функции empty()
find_if(pvec.begin(), pvec.end(), fp);
mem_fn для создания вызываемого объектаЧтобы использовать шаблон
function, следует предоставить сигнатуру вызова члена, который предстоит вызвать. Но можно позволить компилятору вывести тип функции-члена при использовании другого библиотечного средства, шаблона mem_fn, определенного, как и шаблон function, в заголовке functional. Как и шаблон function, шаблон mem_fn создает вызываемый объект из указателя на член класса. В отличие от шаблона function, шаблон mem_fn выведет тип вызываемого объекта из типа указателя на член класса:
find_if(svec.begin(), svec.end(), mem_fn(&string::empty));
Здесь шаблон mem_fn(&string::empty) создает вызываемый объект, получающий строковый аргумент и возвращающий логическое значение.
Вызываемый объект, созданный шаблоном mem_fn, может быть вызван для объекта или указателя:
auto f = mem_fn(&string::empty); // f получает string или string*
f(*svec.begin()); // ok: передача объекта string; f использует .* для
// вызова empty()
f(&svec[0]); // ok: передача указателя на string; f использует .->
// для вызова empty()
Фактически шаблон mem_fn можно считать как будто создающим вызываемый объект с перегруженным оператором вызова функции — один получает тип string*, а другой — string&.
bind() для создания вызываемого объектаДля создания вызываемого объекта из функции-члена можно также использовать функцию bind() (см. раздел 10.3.4):
// связать каждую строку из диапазона
// с неявным первым аргументом empty()
auto it = find_if(svec.begin(), svec.end(),
bind(&string::empty, _1));
Подобно шаблону function, при использовании функции bind() следует сделать явным обычно неявный параметр функции-члена, представляющий объект, с которым будет работать функция-член. Подобно шаблону mem_fn, первый аргумент вызываемого объекта, создаваемого функцией bind(), может быть либо указателем, либо ссылкой на тип string:
auto f = bind(&string::empty, _1);
f(*svec.begin()); // ok: аргумент - строка f, использует .* для вызова
// функции empty()
f(&svec[0]); // ok: аргумент - указатель на строку f использует .->
// для вызова функции empty()
Упражнение 19.18. Напишите функцию, использующую алгоритм count_if() для подсчета количества пустых строк в заданном векторе.
Упражнение 19.19. Напишите функцию, получающую вектор vector<Sales_data> и находящую первый элемент, средняя цена которого превосходит заданное значение.
19.5. Вложенные классы
Класс, определяемый в другом классе, называется вложенным классом (nested class) или вложенным типом (nested type). Вложенные классы обычно используются для классов реализации, как, например, класс QueryResult из приложения текстового запроса (см. раздел 12.3).
Имя вложенного класса видимо в области видимости содержащего его класса, но не вне ее. Имя вложенного класса не будет входить в конфликт с тем же именем, объявленным в другой области видимости.
Вложенный класс может содержать члены тех же видов, что и не вложенный класс. Подобно любому другому классу, вложенный класс контролирует доступ к своим членам при помощи спецификаторов доступа. Содержащий класс не имеет никаких специальных прав доступа к членам вложенного класса, а вложенный класс не имеет привилегий в доступе к членам содержащего его класса.