Упражнение 14.43. Используя библиотечные объекты функций, определите, делимо ли переданное значение типа int на некий элемент в контейнере целых чисел.
14.8.3. Вызываемые объекты и тип function
В языке С++ есть несколько видов вызываемых объектов: функции и указатели на функции, лямбда-выражения (см. раздел 10.3.2), объекты, созданные функцией bind() (см. раздел 10.3.4), и классы с перегруженным оператором вызова функции.
Подобно любому другому объекту, у вызываемого объекта есть тип. Например, у каждого лямбда-выражения есть собственный уникальный (безымянный) тип класса. Типы функций и указателей на функции зависят от типа возвращаемого значения, типа аргумента и т.д.
Однако два вызываемых объекта с разными типами могут иметь ту же
int(int, int)
Функция этого типа получает два числа типа int и возвращает значение типа int.
Иногда необходимо использовать несколько вызываемых объектов с одинаковой сигнатурой вызова, как будто это тот же тип. Рассмотрим, например, следующие разные типы вызываемых объектов:
//
int add(int i, int j) { return i + j; }
//
auto mod = [](int i, int j) { return i % j; };
//
struct div {
int operator()(int denominator, int divisor) {
return denominator / divisor;
}
};
Каждый из этих вызываемых объектов применяет арифметическую операцию к своим параметрам. Даже при том, что у каждого из них разный тип, сигнатура вызова у них одинакова:
int(int, int)
Эти вызываемые объекты можно использовать для написания простого калькулятора. Для этого следует определить
В языке С++ таблицы функций довольно просто реализовать при помощи карт (map). В данном случае как ключ используем строку, соответствующую символу оператора; значение будет функцией, реализующей этот оператор. При необходимости выполнить заданный оператор индексируется карта и осуществляется вызов возвращенного элемента. Если бы все эти функции были автономными и необходимо было использовать только парные операторы для типа int, то карту можно было бы определить так:
//
//
map
Указатель add можно поместить в карту binops следующим образом:
//
binops.insert({"+", add}); // {"+", add} - пара раздел 11.2.3
Но сохранить в карте binops объекты mod или div не получится:
binops.insert({"%", mod}); // ошибка: mod - не указатель на функцию
Проблема в том, что mod — это лямбда-выражение, и у каждого лямбда-выражения есть собственный тип класса. Этот тип не соответствует типу значений, хранимых в карте binops.
functionfunction, определенного в заголовке functional; возможные операции с типом function приведены в табл. 14.3.
Таблица 14.3. Операции с типом function