// ошибка: для вызова через указатель на член класса следует

// использовать оператор .* или ->*

find_if(svec.begin(), svec.end(), fp);

Алгоритм find_if() ожидает вызываемый объект, но предоставляется указатель на функцию-член fp. Этот вызов не будет откомпилирован, поскольку код в алгоритме find_if() выполняет примерно такой оператор:

// проверяет применимость данного предиката к текущему элементу,

// возвращает true

if (fp(*it)) // ошибка: для вызова через указатель на член класса

             // следует использовать оператор ->*

Использование шаблона function для создания вызываемого объекта

Один из способов получения вызываемого объекта из указателя на функцию-член подразумевает использование библиотечного шаблона function (см. раздел 14.8.3):

function fcn = &string::empty;

find_if(svec.begin(), svec.end(), fcn);

Здесь шаблону function указано, что empty() — это функция, которая может быть вызвана со строкой и возвращает значение типа bool. Обычно объект, для которого выполняется функция-член, передается неявному параметру this. Когда шаблон function используется при создании вызываемого объекта для функции-члена, следует преобразовать код так, чтобы сделать этот неявный параметр явным.

Когда объект шаблона function содержит указатель на функцию-член, класс function знает, что для вызова следует использовать соответствующий оператор указателя на член класса. Таким образом, можно предположить, что у функции find_if() будет код наподобие следующего:

// если it является итератором в функции find_if(), то *it - объект

// в заданном диапазоне

if (fcn(*it)) // fcn - имя вызываемого объекта в функции find_if()

Его и выполнит шаблон класса function, используя соответствующий оператор указателя на член класса. Класс function преобразует этот вызов в такой код:

// если it является итератором в функции find_if(), то *it - объект

// в заданном диапазоне

if (((*it).*p)()) // p - указатель на функцию-член в функции fcn

При определении объекта шаблона function следует указать тип функции, сигнатура которой определяет представляемые вызываемые объекты. Когда вызываемой объект является функцией-членом, первый параметр сигнатуры должен представить (обычно неявный) объект, для которого будет выполнена функция-член. Передаваемая шаблону function сигнатура должна определять, будет ли объект передан как указатель или как ссылка.

При определении вызываемого объекта fcn() было известно, что нужно вызвать функцию find_if() для последовательности строковых объектов. Следовательно, от шаблона function требовалось создать вызываемый объект, получающий объекты класса string. Если бы вектор содержал указатели на тип string, от шаблона function требовалось бы ожидать указатель:

vector pvec;

function 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*

Перейти на страницу:

Похожие книги