home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2002 February
/
Chip_2002-02_cd1.bin
/
chplus
/
funktor
/
f15_stl_mem_fun.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
2002-01-02
|
7KB
|
213 lines
//---------------------------------------------------------------------------
#include <iostream>
#include <vector>
#include <list>
#include <algorithm>
#include <functional>
#include <cmath> // std::sqrt
//---------------------------------------------------------------------------
// soubor: f15_stl_mem_fun.cpp
// autor: Jaroslav Franek
// vytvoreno: 20011123
// copyright: (c) 2001 Jaroslav Franek
// umisteni: Chip CD, rubrika Chip Plus, 02/02
// reference: Jak se na funktor vola... II. dil, Chip 02/02
// testovano v : Borland C++ Builder 5.0
// Microsoft Visual C++ .NET 7.0 (beta2)
//
// komentar: stl adaptery pro clenske funkce
// a jejich vytvorujici funkce
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//
// class numero
//
//---------------------------------------------------------------------------
class numero
{
public:
numero() // implicitni konstruktor
: x_(0.0) // (-> implicitni inicializace)
{
}
numero(double x) // jednoparametricky konstruktor
: x_(x) // (-> inicializace prima)
{
}
numero(const numero & n) // kopirovaci konstruktor
: x_(n.x_) // (-> inicializace kopirovanim)
{
}
numero & operator =(const numero & n) // operator prirazeni
{
x_ = n.x_;
return *this;
}
// clenske funkce
//
numero get_sqrt() const; // vrati odmocnene numero
void do_sqrt(); // odmocni "toto" numero
// vypis do datoveho proudu
//
friend std::ostream & operator <<(std::ostream & os, const numero & n)
{
return os << n.x_;
}
private :
double x_;
};
numero numero::get_sqrt() const
{
return numero(std::sqrt(x_));
}
void numero::do_sqrt()
{
x_ = std::sqrt(x_);
}
//---------------------------------------------------------------------------
//
// abychom mohli bezpecne (exception safe) pracovat se seznamem
// ukazatelu na dynamicke instance tridy numero,
// vytvorime si takovy adapter
// (adapter je design pattern se kterym se setkame skoro vsude,
// nejenom u funktoru)
//
//---------------------------------------------------------------------------
class cAdapterSeznamuUkazatelu
{
public:
cAdapterSeznamuUkazatelu(std::list<numero *>::size_type size)
: seznam_(size)
{
// alokujeme data
for ( std::list<numero *>::iterator i(seznam_.begin()); i != seznam_.end(); ++i )
{
*i = new numero();
}
}
template <class InputIterator>
cAdapterSeznamuUkazatelu(InputIterator prvni, InputIterator posledni)
{
while ( prvni != posledni )
{
seznam_.push_back(new numero(*prvni++));
}
}
~cAdapterSeznamuUkazatelu()
{
// uvolnime pamet, kterou zabiraji dynamicke instance
for ( std::list<numero *>::iterator i(seznam_.begin()); i != seznam_.end(); ++i )
{
delete *i;
}
}
// bude nam stacit adaptovat jen par metod
std::list<numero *>::iterator begin()
{
return seznam_.begin();
}
std::list<numero *>::iterator end()
{
return seznam_.end();
}
private:
std::list<numero *> seznam_;
};
// abychom neco (ty numera) videli i pri vypisu seznamu, ktery obsahuje
// pouze ukazatele, udelame malou fintu
//
std::ostream & operator <<(std::ostream & os, const numero * pn)
{
return os << (*pn); // prevedeme to na vypis instance
}
//---------------------------------------------------------------------------
//
// ruzne zpusoby pouziti v akci
//
//---------------------------------------------------------------------------
int main()
{
// pripravime si kontejnery
const int N = 9;
int pole[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
// vysvetlit nasledujici 2 radky zacatecnikovi by zabralo nejmin hodinu
// takze to zatim berme, tak jak je,
// po provedeni bude (zjednodusene:) "numero[i].x_ == pole[i]", v obou pripadech
std::vector<numero> numero_uno(pole, pole + N);
cAdapterSeznamuUkazatelu numero_due(pole, pole + N);
// kontejner pro ulozeni vysledku
std::vector<numero> numero_tre(N); // N prvku
// vypiseme si je na obrazovku,
std::cout << "numero_uno : "; // vypisujeme "numera"
std::copy(numero_uno.begin(), numero_uno.end(), std::ostream_iterator<numero>(std::cout, " "));
std::cout << "\n"
"numero_due : "; // vypisujeme "numera" s fintou, viz vyse
std::copy(numero_due.begin(), numero_due.end(), std::ostream_iterator<numero *>(std::cout, " "));
std::cout << "\n"
"numero_tre : "; // vypisujeme "numera"
std::copy(numero_tre.begin(), numero_tre.end(), std::ostream_iterator<numero>(std::cout, " "));
std::cout << std::endl;
// a ted s tim zacneme cvicit
//*******************************************************************
// nejdrive odmocniny vsech numer z kontejneru numero_uno,
// bez vytvorujici funkce, ulozime do kontejneru numero_tre
std::transform(numero_uno.begin(), numero_uno.end(), numero_tre.begin(),
std::const_mem_fun_ref_t<numero, numero>(&numero::get_sqrt));
//*******************************************************************
// u clenskych funkci nelze vynechat &
// vypiseme si je na obrazovku,
std::cout << "bez vytvorujici funkce\n";
std::cout << "sqrt(numero_uno) : "; // vypisujeme "numera"
std::copy(numero_tre.begin(), numero_tre.end(), std::ostream_iterator<numero>(std::cout, " "));
std::cout << std::endl;
//*******************************************************************
// odmocniny vsech numer z kontejneru numero_uno,
// s vytvorujici funkci, ulozime do kontejneru numero_tre
std::transform(numero_uno.begin(), numero_uno.end(), numero_tre.begin(),
std::mem_fun_ref(&numero::get_sqrt));
//*******************************************************************
// u clenskych funkci nelze vynechat &
// vypiseme si je na obrazovku,
std::cout << "s vytvorujici funkci\n";
std::cout << "sqrt(numero_uno) : "; // vypisujeme "numera"
std::copy(numero_tre.begin(), numero_tre.end(), std::ostream_iterator<numero>(std::cout, " "));
std::cout << std::endl;
//*******************************************************************
// a ted odmocnime numero_due (in-place)
std::for_each(numero_due.begin(), numero_due.end(),
std::mem_fun(&numero::do_sqrt));
//*******************************************************************
// vypiseme si je na obrazovku,
std::cout << "sqrt(numero_due) : "; // vypisujeme "numera" s fintou, viz vyse
std::copy(numero_due.begin(), numero_due.end(), std::ostream_iterator<numero *>(std::cout, " "));
std::cout << std::endl;
return 0;
}
//---------------------------------------------------------------------------