home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2002 February
/
Chip_2002-02_cd1.bin
/
chplus
/
funktor
/
f21_skladani_obecne.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
2002-01-02
|
10KB
|
283 lines
//---------------------------------------------------------------------------
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
#include <cmath>
//---------------------------------------------------------------------------
// soubor: f21_skladani_obecne.cpp
// autor: Jaroslav Franek
// vytvoreno: 20011125
// 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: piseme vlastni adapter - skladani obecnych funktoru
// urceno pro pokrocile programatory - vyzaduje hlubsi znalosti sablon
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// jake jsou moznosti (omezime se na nejvyse binarni funkce):
// oznacime P parametr, U unarni funkce, B binarni funkce
// pak mame
//
// P -> U -> U , vysledna funkce U , oznaceni U_U
//
// P -> U -
// |-> B , vysledna funkce B , oznaceni UU_B
// P -> U /
//
// P -
// |-> B -> U , vysledna funkce B , oznaceni B_U
// P /
//
// pripad nebo
// P -> U - P ------
// |-> B |-> B
// P ---->/ P -> U /
// muzeme realizovat pomoci specialniho unarniho adapteru parametru (argumentu)
// adapterem typu UU_B
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//
// adapter parametru
//
//---------------------------------------------------------------------------
template <class P> class cArgumentIdentity : public std::unary_function<P, P>
{
public:
P operator ()(P arg)
{
return arg;
}
};
// vytvorujici funkce
template <class P> cArgumentIdentity<P> arg(const P &)
{
return cArgumentIdentity<P>();
}
//---------------------------------------------------------------------------
//
// adapter cSkladani_U_U
//
//---------------------------------------------------------------------------
template <class UF1, class UF2> class cSkladani_U_U
: public std::unary_function
<
typename UF1::argument_type,
typename UF2::result_type
>
{
public:
cSkladani_U_U(UF1 inner, UF2 outer)
: inner_(inner),
outer_(outer)
{
}
typename UF2::result_type operator ()(typename UF1::argument_type x)
{
return outer_(inner_(x)); // zretezeni
}
protected:
// idealne by tyhle dva mely byt stejne,
// ale obecne postaci, kdyz prvni lze prevest na druhy
typedef typename UF1::result_type inner_result_type;
typedef typename UF2::argument_type outer_argument_type;
private:
UF1 inner_;
UF2 outer_;
};
// vytvorujici funkce
template <class UF1, class UF2>
cSkladani_U_U<UF1, UF2> slozit_u_u(const UF1 & uf1, const UF2 & uf2)
{
return cSkladani_U_U<UF1, UF2>(uf1, uf2);
}
//---------------------------------------------------------------------------
//
// adapter cSkladani_UU_B
//
//---------------------------------------------------------------------------
template <class UFX, class UFY, class BF> class cSkladani_UU_B
: public std::binary_function
<
typename UFX::argument_type,
typename UFY::argument_type,
typename BF::result_type
>
{
public:
cSkladani_UU_B(UFX innerx, UFY innery, BF outer)
: innerx_(innerx),
innery_(innery),
outer_(outer)
{
}
typename BF::result_type operator ()(typename UFX::argument_type x,
typename UFY::argument_type y)
{
return outer_(innerx_(x), innery_(y)); // zretezeni
}
protected:
// idealne by tyhle dva mely byt stejne,
// ale obecne postaci, kdyz prvni lze prevest na druhy
typedef typename UFX::result_type innerx_result_type;
typedef typename BF::first_argument_type outer_first_argument_type;
// idealne by tyhle dva mely byt stejne,
// ale obecne postaci, kdyz prvni lze prevest na druhy
typedef typename UFY::result_type innery_result_type;
typedef typename BF::second_argument_type outer_second_argument_type;
private:
UFX innerx_;
UFY innery_;
BF outer_;
};
// vytvorujici funkce
template <class UFX, class UFY, class BF>
cSkladani_UU_B<UFX, UFY, BF> slozit_uu_b(const UFX & ufx, const UFY & ufy, const BF & bf)
{
return cSkladani_UU_B<UFX, UFY, BF>(ufx, ufy, bf);
}
//---------------------------------------------------------------------------
//
// adapter cSkladani_B_U
//
//---------------------------------------------------------------------------
template <class BF, class UF> class cSkladani_B_U
: public std::binary_function
<
typename BF::first_argument_type,
typename BF::second_argument_type,
typename UF::result_type
>
{
public:
cSkladani_B_U(BF inner, UF outer)
: inner_(inner),
outer_(outer)
{
}
typename UF::result_type operator ()(typename BF::first_argument_type x,
typename BF::second_argument_type y)
{
return outer_(inner_(x, y)); // zretezeni
}
protected:
// idealne by tyhle dva mely byt stejne,
// ale obecne postaci, kdyz prvni lze prevest na druhy
typedef typename BF::result_type inner_result_type;
typedef typename UF::argument_type outer_argument_type;
private:
BF inner_;
UF outer_;
};
// vytvorujici funkce
template <class BF, class UF>
cSkladani_B_U<BF, UF> slozit_b_u(const BF & bf, const UF & uf)
{
return cSkladani_B_U<BF, UF>(bf, uf);
}
//---------------------------------------------------------------------------
//
// ukazka, jak to funguje v praxi
//
//---------------------------------------------------------------------------
int main()
{
// nejdrive si pripravime pole
const int N = 9;
int pole1[] = { -1, -2, 3, -4, 0, -6, 0, -8, 9 };
int pole2[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1 };
// a ted STL kontejner
std::vector<double> cisla1(pole1, pole1 + N); // N prvku, pole1[i]
std::vector<double> cisla2(pole2, pole2 + N); // N prvku, pole2[i]
std::vector<double> odmocniny(N); // N prvku
std::vector<double> druhy(N); // N prvku
std::vector<double> treti(N); // N prvku
//*******************************************************************
// pouziti adapteru U_U
// kdybychom pouzili druhou odmocninu, neproslo by to,
// protoze tam mame zaporna cisla, takze nejdriv zavolame
// absolutni hodnotu a pak teprve druhou odmocninu
// vysledky ulozime do vektoru 'odmocniny'
std::transform(cisla1.begin(), cisla1.end(), odmocniny.begin(),
slozit_u_u(std::ptr_fun(std::fabs), std::ptr_fun(std::sqrt)));
//*******************************************************************
// vypiseme si to
std::cout << "cisla1 : ";
std::copy(cisla1.begin(), cisla1.end(), std::ostream_iterator<double>(std::cout, " "));
std::cout << "\n"
"sqrt(abs(cisla1)) : ";
std::copy(odmocniny.begin(), odmocniny.end(), std::ostream_iterator<double>(std::cout, " "));
std::cout << std::endl;
//*******************************************************************
// pouziti adapteru UU_B
// prvni pole: udelame absolutni hodnoty
// druhe pole nechame jak je (adapter cArgument)
// binarni operace: secteme to, cili std::plus<double>
// vysledky ulozime do vektoru 'druhy'
std::transform(cisla1.begin(), cisla1.end(), cisla2.begin(), druhy.begin(),
slozit_uu_b(std::ptr_fun(std::fabs), arg(*cisla2.begin()),
std::plus<double>())); // *cisla.begin() jen urcuje sptavny typ
//*******************************************************************
// vypiseme si to
std::cout << "cisla1 : ";
std::copy(cisla1.begin(), cisla1.end(), std::ostream_iterator<double>(std::cout, " "));
std::cout << "\n"
"cisla2 : ";
std::copy(cisla2.begin(), cisla2.end(), std::ostream_iterator<double>(std::cout, " "));
std::cout << "\n"
"abs(cisla1) + cisla2 : ";
std::copy(druhy.begin(), druhy.end(), std::ostream_iterator<double>(std::cout, " "));
std::cout << std::endl;
//*******************************************************************
// pouziti adapteru B_U
// secteme prvni a druhe pole (po slozkach)
// a pak z toho udelame absolutni hodnotu
// vysledky ulozime do vektoru 'treti'
std::transform(cisla1.begin(), cisla1.end(), cisla2.begin(), treti.begin(),
slozit_b_u(std::plus<double>(), std::ptr_fun(std::fabs)));
//*******************************************************************
// vypiseme si to
std::cout << "cisla1 : ";
std::copy(cisla1.begin(), cisla1.end(), std::ostream_iterator<double>(std::cout, " "));
std::cout << "\n"
"cisla2 : ";
std::copy(cisla2.begin(), cisla2.end(), std::ostream_iterator<double>(std::cout, " "));
std::cout << "\n"
"abs(cisla1 + cisla2) : ";
std::copy(treti.begin(), treti.end(), std::ostream_iterator<double>(std::cout, " "));
std::cout << std::endl;
// spravnost vysledku jiste dokazete overit sami
return 0;
}
//---------------------------------------------------------------------------