Читаем Thinking In C++. Volume 2: Practical Programming полностью

<p>Function pointer adapters</p>

Wherever a function-like entity is expected by an algorithm, you can supply either a pointer to an ordinary function or a function object. When the algorithm issues a call, if it is through a function pointer, than the native function-call mechanism is used. If it through a function object, then that objects operator( ) member executes. You saw earlier, for example, that we passed a raw function, gt15( ), as a predicate to remove_copy_if( ) in the program CopyInts2.cpp. We also passed pointers to functions returning random numbers to generate( ) and generate_n( ).

You cannot, however, use raw functions with function object adapters, such as bind2nd( ), because they assume the existence of type definitions for the argument and result types. Instead of manually converting your native functions into function objects yourself, the standard library provides a family of adapters to do the work for you. The ptr_fun( ) adapters take a pointer to a function and turn it into a function object. They are not designed for a function that takes no arguments—they must only be used with unary functions or binary functions.

The following program uses ptr_fun( ) to wrap a unary function.

//: C06:PtrFun1.cpp

// Using ptr_fun() with a unary function

#include

#include

#include

#include

#include

#include

using namespace std;

int d[] = {123, 94, 10, 314, 315};

const int dsz = sizeof d / sizeof *d;

bool isEven(int x) {

  return x % 2 == 0;

}

int main() {

  vector vb;

  transform(d, d + dsz, back_inserter(vb),

    not1(ptr_fun(isEven)));

  copy(vb.begin(), vb.end(),

    ostream_iterator(cout, " "));

  cout << endl;

  // Output: 1 0 0 0 1

} ///:~

We can’t simply pass isEven to not1, because not1 needs to know the actual argument type and return type its argument uses. The ptr_fun( ) adapter deduces those types through template argument deduction. The definition of the unary version of ptr_fun( ) looks something like this:.

template

pointer_to_unary_function

ptr_fun(Result (*fptr)(Arg))

{

  return pointer_to_unary_function(fptr);

}

As you can see, this version of ptr_fun( ) deduces the argument and result types from fptr and uses them to initialize a pointer_to_unary_function object that stores fptr. The function call operator for pointer_to_unary_function just calls fptr, as you can see by the last line of its code:.

template

class pointer_to_unary_function

: public unary_function {

  Result (*fptr)(Arg); // stores the f-ptr

public:

  pointer_to_unary_function(Result (*x)(Arg))

    : fptr(x) {}

  Result operator()(Arg x) const {return fptr(x);}

};

Since pointer_to_unary_function derives from unary_function, the appropriate type definitions come along for the ride and are available to not1.

There is also a binary version of ptr_fun( ), which returns a pointer_to_binary_function object (which derives from binary_function, of course) that behaves analogously to the unary case. The following program uses the binary version of ptr_fun( ) to raise numbers in a sequence to a power. It also reveals a "gotcha" when passing overloaded functions to ptr_fun( ).

//: C06:PtrFun2.cpp

// Using ptr_fun() for a binary function

#include

#include

#include

#include

#include

#include

using namespace std;

double d[] = { 01.23, 91.370, 56.661,

  023.230, 19.959, 1.0, 3.14159 };

const int dsz = sizeof d / sizeof *d;

int main() {

  vector vd;

  transform(d, d + dsz, back_inserter(vd),

    bind2nd(ptr_fun(pow), 2.0));

  copy(vd.begin(), vd.end(),

    ostream_iterator(cout, " "));

  cout << endl;

} ///:~

The pow( ) function is overloaded in the standard C++ header for each of the floating-point data types, as follows:

float pow(float, int);  // efficient int power versions…

double pow(double, int);

long double pow(long double, int);

float pow(float, float);

double pow(double, double);

long double pow(long double, long double);

Since there are multiple versions of pow( ), the compiler has no way of knowing which to choose. In this case, we have to help the compiler by using explicit function template specialization, as explained in the previous chapter.

An even trickier problem is that of converting a member function into a function object suitable for using with the generic algorithms. As a simple example, suppose we have the classical "shape" problem and want to apply the draw( ) member function to each pointer in a container of Shape:.

//: C06:MemFun1.cpp

// Applying pointers to member functions

#include

#include

#include

#include

#include "../purge.h"

using namespace std;

class Shape {

public:

  virtual void draw() = 0;

  virtual ~Shape() {}

};

class Circle : public Shape {

public:

  virtual void draw() {

    cout << "Circle::Draw()" << endl;

  }

  ~Circle() {

    cout << "Circle::~Circle()" << endl;

  }

};

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

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

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных