home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 February / Chip_2002-02_cd1.bin / chplus / funktor / f21_skladani_obecne.cpp < prev    next >
C/C++ Source or Header  |  2002-01-02  |  10KB  |  283 lines

  1. //---------------------------------------------------------------------------
  2.  
  3. #include <iostream>
  4. #include <vector>
  5. #include <algorithm>
  6. #include <functional>
  7. #include <cmath>
  8.  
  9. //---------------------------------------------------------------------------
  10. //  soubor:    f21_skladani_obecne.cpp
  11. //  autor:     Jaroslav Franek
  12. //  vytvoreno: 20011125
  13. //  copyright: (c) 2001 Jaroslav Franek
  14. //  umisteni:  Chip CD, rubrika Chip Plus, 02/02
  15. //  reference: Jak se na funktor vola... II. dil, Chip 02/02
  16. //  testovano v : Borland C++ Builder 5.0
  17. //                Microsoft Visual C++ .NET 7.0 (beta2)
  18. //
  19. //  komentar:  piseme vlastni adapter - skladani obecnych funktoru
  20. //             urceno pro pokrocile programatory - vyzaduje hlubsi znalosti sablon
  21. //---------------------------------------------------------------------------
  22.  
  23. //---------------------------------------------------------------------------
  24. //  jake jsou moznosti (omezime se na nejvyse binarni funkce):
  25. //  oznacime P parametr, U unarni funkce, B binarni funkce
  26. //  pak mame
  27. //
  28. //    P -> U -> U , vysledna funkce U , oznaceni U_U
  29. //
  30. //    P -> U -
  31. //            |-> B , vysledna funkce B , oznaceni UU_B
  32. //    P -> U /
  33. //
  34. //    P -
  35. //       |-> B -> U , vysledna funkce B , oznaceni B_U
  36. //    P /
  37. //
  38. //  pripad            nebo
  39. //    P -> U -              P ------
  40. //            |-> B                 |-> B
  41. //    P ---->/              P -> U /
  42. //  muzeme realizovat pomoci specialniho unarniho adapteru parametru (argumentu)
  43. //  adapterem typu UU_B
  44. //---------------------------------------------------------------------------
  45.  
  46. //---------------------------------------------------------------------------
  47. //
  48. //  adapter parametru
  49. //
  50. //---------------------------------------------------------------------------
  51.  
  52. template <class P> class cArgumentIdentity : public std::unary_function<P, P>
  53. {
  54. public:
  55.    P operator ()(P arg)
  56.       {
  57.          return arg;
  58.       }
  59. };
  60.  
  61. // vytvorujici funkce
  62. template <class P> cArgumentIdentity<P> arg(const P &)
  63. {
  64.    return cArgumentIdentity<P>();
  65. }
  66.  
  67. //---------------------------------------------------------------------------
  68. //
  69. //  adapter cSkladani_U_U
  70. //
  71. //---------------------------------------------------------------------------
  72.  
  73. template <class UF1, class UF2> class cSkladani_U_U
  74.    : public std::unary_function
  75.             <
  76.                typename UF1::argument_type,
  77.                typename UF2::result_type
  78.             >
  79. {
  80. public:
  81.    cSkladani_U_U(UF1 inner, UF2 outer)
  82.       : inner_(inner),
  83.         outer_(outer)
  84.       {
  85.       }
  86.    typename UF2::result_type operator ()(typename UF1::argument_type x)
  87.       {
  88.          return outer_(inner_(x));  // zretezeni
  89.       }
  90. protected:
  91.    // idealne by tyhle dva mely byt stejne,
  92.    // ale obecne postaci, kdyz prvni lze prevest na druhy
  93.    typedef typename UF1::result_type inner_result_type;
  94.    typedef typename UF2::argument_type outer_argument_type;
  95. private:
  96.    UF1 inner_;
  97.    UF2 outer_;
  98. };
  99.  
  100. // vytvorujici funkce
  101. template <class UF1, class UF2>
  102. cSkladani_U_U<UF1, UF2> slozit_u_u(const UF1 & uf1, const UF2 & uf2)
  103. {
  104.    return cSkladani_U_U<UF1, UF2>(uf1, uf2);
  105. }
  106.  
  107. //---------------------------------------------------------------------------
  108. //
  109. //  adapter cSkladani_UU_B
  110. //
  111. //---------------------------------------------------------------------------
  112.  
  113. template <class UFX, class UFY, class BF> class cSkladani_UU_B
  114.    : public std::binary_function
  115.             <
  116.                typename UFX::argument_type,
  117.                typename UFY::argument_type,
  118.                typename BF::result_type
  119.             >
  120. {
  121. public:
  122.    cSkladani_UU_B(UFX innerx, UFY innery, BF outer)
  123.       : innerx_(innerx),
  124.         innery_(innery),
  125.         outer_(outer)
  126.       {
  127.       }
  128.    typename BF::result_type operator ()(typename UFX::argument_type x,
  129.                                         typename UFY::argument_type y)
  130.       {
  131.          return outer_(innerx_(x), innery_(y));  // zretezeni
  132.       }
  133. protected:
  134.    // idealne by tyhle dva mely byt stejne,
  135.    // ale obecne postaci, kdyz prvni lze prevest na druhy
  136.    typedef typename UFX::result_type innerx_result_type;
  137.    typedef typename BF::first_argument_type outer_first_argument_type;
  138.    // idealne by tyhle dva mely byt stejne,
  139.    // ale obecne postaci, kdyz prvni lze prevest na druhy
  140.    typedef typename UFY::result_type innery_result_type;
  141.    typedef typename BF::second_argument_type outer_second_argument_type;
  142. private:
  143.    UFX innerx_;
  144.    UFY innery_;
  145.    BF outer_;
  146. };
  147.  
  148. // vytvorujici funkce
  149. template <class UFX, class UFY, class BF>
  150. cSkladani_UU_B<UFX, UFY, BF> slozit_uu_b(const UFX & ufx, const UFY & ufy, const BF & bf)
  151. {
  152.    return cSkladani_UU_B<UFX, UFY, BF>(ufx, ufy, bf);
  153. }
  154.  
  155. //---------------------------------------------------------------------------
  156. //
  157. //  adapter cSkladani_B_U
  158. //
  159. //---------------------------------------------------------------------------
  160.  
  161. template <class BF, class UF> class cSkladani_B_U
  162.    : public std::binary_function
  163.             <
  164.                typename BF::first_argument_type,
  165.                typename BF::second_argument_type,
  166.                typename UF::result_type
  167.             >
  168. {
  169. public:
  170.    cSkladani_B_U(BF inner, UF outer)
  171.       : inner_(inner),
  172.         outer_(outer)
  173.       {
  174.       }
  175.    typename UF::result_type operator ()(typename BF::first_argument_type x,
  176.                                         typename BF::second_argument_type y)
  177.       {
  178.          return outer_(inner_(x, y));  // zretezeni
  179.       }
  180. protected:
  181.    // idealne by tyhle dva mely byt stejne,
  182.    // ale obecne postaci, kdyz prvni lze prevest na druhy
  183.    typedef typename BF::result_type inner_result_type;
  184.    typedef typename UF::argument_type outer_argument_type;
  185. private:
  186.    BF inner_;
  187.    UF outer_;
  188. };
  189.  
  190. // vytvorujici funkce
  191. template <class BF, class UF>
  192. cSkladani_B_U<BF, UF> slozit_b_u(const BF & bf, const UF & uf)
  193. {
  194.    return cSkladani_B_U<BF, UF>(bf, uf);
  195. }
  196.  
  197. //---------------------------------------------------------------------------
  198. //
  199. //  ukazka, jak to funguje v praxi
  200. //
  201. //---------------------------------------------------------------------------
  202.  
  203. int main()
  204. {
  205.    // nejdrive si pripravime pole
  206.    const int N = 9;
  207.    int pole1[] = { -1, -2, 3, -4, 0, -6, 0, -8, 9 };
  208.    int pole2[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1 };
  209.  
  210.    // a ted STL kontejner
  211.    std::vector<double> cisla1(pole1, pole1 + N);   // N prvku, pole1[i]
  212.    std::vector<double> cisla2(pole2, pole2 + N);   // N prvku, pole2[i]
  213.    std::vector<double> odmocniny(N);            // N prvku
  214.    std::vector<double> druhy(N);            // N prvku
  215.    std::vector<double> treti(N);            // N prvku
  216.  
  217. //*******************************************************************
  218.    // pouziti adapteru U_U
  219.    // kdybychom pouzili druhou odmocninu, neproslo by to,
  220.    // protoze tam mame zaporna cisla, takze nejdriv zavolame
  221.    // absolutni hodnotu a pak teprve druhou odmocninu
  222.    // vysledky ulozime do vektoru 'odmocniny'
  223.    std::transform(cisla1.begin(), cisla1.end(), odmocniny.begin(),
  224.                   slozit_u_u(std::ptr_fun(std::fabs), std::ptr_fun(std::sqrt)));
  225. //*******************************************************************
  226.  
  227.    // vypiseme si to
  228.    std::cout << "cisla1    : ";
  229.    std::copy(cisla1.begin(), cisla1.end(), std::ostream_iterator<double>(std::cout, "  "));
  230.    std::cout << "\n"
  231.                 "sqrt(abs(cisla1)) : ";
  232.    std::copy(odmocniny.begin(), odmocniny.end(), std::ostream_iterator<double>(std::cout, "  "));
  233.    std::cout << std::endl;
  234.  
  235. //*******************************************************************
  236.    // pouziti adapteru UU_B
  237.    // prvni pole: udelame absolutni hodnoty
  238.    // druhe pole nechame jak je (adapter cArgument)
  239.    // binarni operace: secteme to, cili std::plus<double>
  240.    // vysledky ulozime do vektoru 'druhy'
  241.    std::transform(cisla1.begin(), cisla1.end(), cisla2.begin(), druhy.begin(),
  242.                   slozit_uu_b(std::ptr_fun(std::fabs), arg(*cisla2.begin()),
  243.                               std::plus<double>()));      // *cisla.begin() jen urcuje sptavny typ
  244. //*******************************************************************
  245.  
  246.    // vypiseme si to
  247.    std::cout << "cisla1    : ";
  248.    std::copy(cisla1.begin(), cisla1.end(), std::ostream_iterator<double>(std::cout, "  "));
  249.    std::cout << "\n"
  250.                 "cisla2    : ";
  251.    std::copy(cisla2.begin(), cisla2.end(), std::ostream_iterator<double>(std::cout, "  "));
  252.    std::cout << "\n"
  253.                 "abs(cisla1) + cisla2 : ";
  254.    std::copy(druhy.begin(), druhy.end(), std::ostream_iterator<double>(std::cout, "  "));
  255.    std::cout << std::endl;
  256.  
  257. //*******************************************************************
  258.    // pouziti adapteru B_U
  259.    // secteme prvni a druhe pole (po slozkach)
  260.    // a pak z toho udelame absolutni hodnotu
  261.    // vysledky ulozime do vektoru 'treti'
  262.    std::transform(cisla1.begin(), cisla1.end(), cisla2.begin(), treti.begin(),
  263.                   slozit_b_u(std::plus<double>(), std::ptr_fun(std::fabs)));
  264. //*******************************************************************
  265.  
  266.    // vypiseme si to
  267.    std::cout << "cisla1    : ";
  268.    std::copy(cisla1.begin(), cisla1.end(), std::ostream_iterator<double>(std::cout, "  "));
  269.    std::cout << "\n"
  270.                 "cisla2    : ";
  271.    std::copy(cisla2.begin(), cisla2.end(), std::ostream_iterator<double>(std::cout, "  "));
  272.    std::cout << "\n"
  273.                 "abs(cisla1 + cisla2) : ";
  274.    std::copy(treti.begin(), treti.end(), std::ostream_iterator<double>(std::cout, "  "));
  275.    std::cout << std::endl;
  276.  
  277.    // spravnost vysledku jiste dokazete overit sami
  278.  
  279.    return 0;
  280. }
  281. //---------------------------------------------------------------------------
  282.  
  283.