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

  1. //---------------------------------------------------------------------------
  2.  
  3. #include <iostream>
  4. #include <vector>
  5. #include <list>
  6. #include <algorithm>
  7. #include <functional>
  8. #include <cmath>         // std::sqrt
  9.  
  10. //---------------------------------------------------------------------------
  11. //  soubor:    f15_stl_mem_fun.cpp
  12. //  autor:     Jaroslav Franek
  13. //  vytvoreno: 20011123
  14. //  copyright: (c) 2001 Jaroslav Franek
  15. //  umisteni:  Chip CD, rubrika Chip Plus, 02/02
  16. //  reference: Jak se na funktor vola... II. dil, Chip 02/02
  17. //  testovano v : Borland C++ Builder 5.0
  18. //                Microsoft Visual C++ .NET 7.0 (beta2)
  19. //
  20. //  komentar:  stl adaptery pro clenske funkce
  21. //             a jejich vytvorujici funkce
  22. //---------------------------------------------------------------------------
  23.  
  24. //---------------------------------------------------------------------------
  25. //
  26. //  class numero
  27. //
  28. //---------------------------------------------------------------------------
  29.  
  30. class numero
  31. {
  32. public:
  33.    numero()                     // implicitni konstruktor
  34.       : x_(0.0)                 // (-> implicitni inicializace)
  35.       {
  36.       }
  37.    numero(double x)             // jednoparametricky konstruktor
  38.       : x_(x)                   // (-> inicializace prima)
  39.       {
  40.       }
  41.    numero(const numero & n)     // kopirovaci konstruktor
  42.       : x_(n.x_)                // (-> inicializace kopirovanim)
  43.       {
  44.       }
  45.    numero & operator =(const numero & n)  // operator prirazeni
  46.       {
  47.          x_ = n.x_;
  48.          return *this;
  49.       }
  50.    // clenske funkce
  51.    //
  52.    numero get_sqrt() const; // vrati odmocnene numero
  53.    void do_sqrt();          // odmocni "toto" numero
  54.  
  55.    //  vypis do datoveho proudu
  56.    //
  57.    friend std::ostream & operator <<(std::ostream & os, const numero & n)
  58.       {
  59.          return os << n.x_;
  60.       }
  61. private :
  62.    double x_;
  63. };
  64.  
  65. numero numero::get_sqrt() const
  66. {
  67.    return numero(std::sqrt(x_));
  68. }
  69.  
  70. void numero::do_sqrt()
  71. {
  72.    x_ = std::sqrt(x_);
  73. }
  74.  
  75. //---------------------------------------------------------------------------
  76. //
  77. //  abychom mohli bezpecne (exception safe) pracovat se seznamem
  78. //  ukazatelu na dynamicke instance tridy numero,
  79. //  vytvorime si takovy adapter
  80. //  (adapter je design pattern se kterym se setkame skoro vsude,
  81. //   nejenom u funktoru)
  82. //
  83. //---------------------------------------------------------------------------
  84.  
  85. class cAdapterSeznamuUkazatelu
  86. {
  87. public:
  88.    cAdapterSeznamuUkazatelu(std::list<numero *>::size_type size)
  89.       : seznam_(size)
  90.       {
  91.          // alokujeme data
  92.          for ( std::list<numero *>::iterator i(seznam_.begin()); i != seznam_.end(); ++i )
  93.          {
  94.             *i = new numero();
  95.          }
  96.       }
  97.  
  98.    template <class InputIterator>
  99.    cAdapterSeznamuUkazatelu(InputIterator prvni, InputIterator posledni)
  100.       {
  101.          while ( prvni != posledni )
  102.          {
  103.             seznam_.push_back(new numero(*prvni++));
  104.          }
  105.       }
  106.  
  107.    ~cAdapterSeznamuUkazatelu()
  108.       {
  109.          // uvolnime pamet, kterou zabiraji dynamicke instance
  110.          for ( std::list<numero *>::iterator i(seznam_.begin()); i != seznam_.end(); ++i )
  111.          {
  112.             delete *i;
  113.          }
  114.       }
  115.  
  116.    // bude nam stacit adaptovat jen par metod
  117.    std::list<numero *>::iterator begin()
  118.       {
  119.          return seznam_.begin();
  120.       }
  121.    std::list<numero *>::iterator end()
  122.       {
  123.          return seznam_.end();
  124.       }
  125.  
  126. private:
  127.    std::list<numero *> seznam_;
  128. };
  129.  
  130. //  abychom neco (ty numera) videli i pri vypisu seznamu, ktery obsahuje
  131. //  pouze ukazatele, udelame malou fintu
  132. //
  133. std::ostream & operator <<(std::ostream & os, const numero * pn)
  134. {
  135.    return os << (*pn);  // prevedeme to na vypis instance
  136. }
  137.  
  138. //---------------------------------------------------------------------------
  139. //
  140. //  ruzne zpusoby pouziti v akci
  141. //
  142. //---------------------------------------------------------------------------
  143.  
  144. int main()
  145. {
  146.    // pripravime si kontejnery
  147.    const int N = 9;
  148.    int pole[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
  149.  
  150.    // vysvetlit nasledujici 2 radky zacatecnikovi by zabralo nejmin hodinu
  151.    // takze to zatim berme, tak jak je,
  152.    // po provedeni bude (zjednodusene:) "numero[i].x_ == pole[i]", v obou pripadech
  153.    std::vector<numero> numero_uno(pole, pole + N);
  154.    cAdapterSeznamuUkazatelu numero_due(pole, pole + N);
  155.  
  156.    // kontejner pro ulozeni vysledku
  157.    std::vector<numero> numero_tre(N);   // N prvku
  158.  
  159.    // vypiseme si je na obrazovku,
  160.    std::cout << "numero_uno : ";                          // vypisujeme "numera"
  161.    std::copy(numero_uno.begin(), numero_uno.end(), std::ostream_iterator<numero>(std::cout, "  "));
  162.    std::cout << "\n"
  163.                 "numero_due : ";                          // vypisujeme "numera" s fintou, viz vyse
  164.    std::copy(numero_due.begin(), numero_due.end(), std::ostream_iterator<numero *>(std::cout, "  "));
  165.    std::cout << "\n"
  166.                 "numero_tre : ";                          // vypisujeme "numera"
  167.    std::copy(numero_tre.begin(), numero_tre.end(), std::ostream_iterator<numero>(std::cout, "  "));
  168.    std::cout << std::endl;
  169.  
  170.    // a ted s tim zacneme cvicit
  171. //*******************************************************************
  172.    // nejdrive odmocniny vsech numer z kontejneru numero_uno,
  173.    // bez vytvorujici funkce, ulozime do kontejneru numero_tre
  174.    std::transform(numero_uno.begin(), numero_uno.end(), numero_tre.begin(),
  175.                   std::const_mem_fun_ref_t<numero, numero>(&numero::get_sqrt));
  176. //*******************************************************************
  177.                       // u clenskych funkci nelze vynechat &
  178.  
  179.    // vypiseme si je na obrazovku,
  180.    std::cout << "bez vytvorujici funkce\n";
  181.    std::cout << "sqrt(numero_uno) : ";                    // vypisujeme "numera"
  182.    std::copy(numero_tre.begin(), numero_tre.end(), std::ostream_iterator<numero>(std::cout, "  "));
  183.    std::cout << std::endl;
  184.  
  185. //*******************************************************************
  186.    // odmocniny vsech numer z kontejneru numero_uno,
  187.    // s vytvorujici funkci, ulozime do kontejneru numero_tre
  188.    std::transform(numero_uno.begin(), numero_uno.end(), numero_tre.begin(),
  189.                   std::mem_fun_ref(&numero::get_sqrt));
  190. //*******************************************************************
  191.    // u clenskych funkci nelze vynechat &
  192.  
  193.    // vypiseme si je na obrazovku,
  194.    std::cout << "s vytvorujici funkci\n";
  195.    std::cout << "sqrt(numero_uno) : ";                    // vypisujeme "numera"
  196.    std::copy(numero_tre.begin(), numero_tre.end(), std::ostream_iterator<numero>(std::cout, "  "));
  197.    std::cout << std::endl;
  198.  
  199. //*******************************************************************
  200.    // a ted odmocnime numero_due (in-place)
  201.    std::for_each(numero_due.begin(), numero_due.end(),
  202.                  std::mem_fun(&numero::do_sqrt));
  203. //*******************************************************************
  204.  
  205.    // vypiseme si je na obrazovku,
  206.    std::cout << "sqrt(numero_due) : ";                    // vypisujeme "numera" s fintou, viz vyse
  207.    std::copy(numero_due.begin(), numero_due.end(), std::ostream_iterator<numero *>(std::cout, "  "));
  208.    std::cout << std::endl;
  209.  
  210.    return 0;
  211. }
  212. //---------------------------------------------------------------------------
  213.