Funkcjonalny (C++)

W kontekście języka programowania C++ funkcjonał odnosi się do pliku nagłówkowego , który jest częścią standardowej biblioteki C++ i zawiera zestaw predefiniowanych szablonów klas dla obiektów funkcyjnych , w tym operacje arytmetyczne, porównania i logikę. Instancje tych szablonów klas to klasy C++ , które definiują operator wywołania funkcji , a instancje tych klas można wywoływać tak, jakby były funkcjami . Możliwe jest wykonywanie bardzo skomplikowanych operacji bez pisania nowego obiektu funkcyjnego, po prostu przez połączenie predefiniowanych obiektów funkcyjnych i adapterów obiektów funkcyjnych.

Szablon klasy std::function dostarczany przez C++ 11 to opakowanie funkcji polimorficznej ogólnego przeznaczenia . Instancje std::function mogą przechowywać, kopiować i wywoływać dowolne wywoływalne cele — funkcje, wyrażenia lambda (wyrażenia definiujące funkcje anonimowe ), wyrażenia wiązania (instancje adapterów funkcji, które przekształcają funkcje w inne funkcje o mniejszej liczbie liczb , dostarczając wartości dla niektórych argumenty) lub inne obiekty funkcyjne.

Algorytmy udostępniane przez standardową bibliotekę języka C++ nie wymagają obiektów funkcyjnych o więcej niż dwóch argumentach. Ważnym przypadkiem specjalnym są obiekty funkcyjne, które zwracają wartości logiczne . Funkcja jednoargumentowa , której typem zwracanym jest bool , nazywana jest predykatem , a funkcja binarna, której typem zwracanym jest bool , nazywana jest predykatem binarnym .

Adaptowalne obiekty funkcyjne

Ogólnie rzecz biorąc, obiekt funkcji ma ograniczenia co do typu swojego argumentu. Ograniczenia typu nie muszą być jednak proste: operator () może być przeciążony lub może być szablonem składowym. Podobnie program nie musi mieć możliwości określenia, jakie są te ograniczenia. Adaptowalny obiekt funkcji określa jednak, jakie są typy argumentów i wartości zwracanych, oraz zapewnia zagnieżdżone definicje typów , dzięki czemu typy te mogą być nazywane i używane w programach. Jeśli typ F0 jest modelem adaptowalnego generatora, to musi definiować F0 :: typ_wyniku . Podobnie, jeśli F1 jest modelem adaptowalnej funkcji jednoargumentowej, musi definiować F1 :: typ_argumentu i F1 :: typ_wyniku , a jeśli F2 jest modelem adaptowalnej funkcji binarnej, musi definiować F2 :: typ_argumentu , F2 :: typ_drugiego argumentu i F2 :: typ_wyniku . Biblioteka standardowa języka C++ udostępnia klasy podstawowe unary_function i binary_function , aby uprościć definiowanie adaptowalnych funkcji jednoargumentowych i adaptowalnych funkcji binarnych.

Adaptowalne obiekty funkcyjne są ważne, ponieważ mogą być używane przez adaptery obiektów funkcyjnych: obiekty funkcyjne, które przekształcają lub manipulują innymi obiektami funkcyjnymi. Biblioteka standardowa C++ udostępnia wiele różnych adapterów obiektów funkcji, w tym unary_negate (który zwraca logiczne uzupełnienie wartości zwracanej przez określony predykat z możliwością dostosowania) oraz unary_compose i binary_compose , które wykonują kompozycję obiektu funkcji.

Predefiniowane obiekty funkcyjne

Biblioteka standardowa C++ zawiera w pliku nagłówkowym funkcjonalnym wiele różnych predefiniowanych obiektów funkcyjnych, w tym operacje arytmetyczne ( plus , minus , mnożenie , dzielenie , moduł i negacja ), porównania ( równa się , not_równość , większa , mniejsza , większa_równość i mniejsza_równość ), i operacje logiczne ( logiczne_i , logiczne_or i logiczne_nie ).

Przykłady

Opakowania funkcji mogą być używane do wywoływania zwykłych funkcji lub obiektów funkcji utworzonych przez wyrażenia lambda.

 
 


  
   
      


  
  
     
  

  
     
  

  
       
        
  
  

  


      
  

  


    
       
  
 #include  <iostream>  #include  <functional>  /* Zdefiniuj funkcję szablonu */  template  <  nazwa typu  T  >  void  PrintValue  (  wartość  T  )  {  std  ::  cout  <<  wartość  <<  std  ::  endl  ;  }  int  main  (  void  )  {  /* Opakowanie funkcji dla funkcji */  std  ::  function  <  void  (  int  )  >  func_a  =  PrintValue  <  int  >  ;  func_a  (  2015  );  /* Opakowanie funkcji na wskaźnik funkcji */  std  ::  function  <  void  (  int  )  >  func_b  =  &  PrintValue  <  int  >  ;  func_b  (  2016  );  /* Opakowanie funkcji dla funkcji lambda. */   std  ::  function  <  void  (  int  )  >  func_c  =  [] (  int  value  )  {  std  ::  cout  <<  wartość  <<  std  ::  endl  ;  };  func_c  (  2017  );  /* Opakowanie funkcji wygenerowane przez std::bind().  * Przekaż predefiniowany parametr podczas wiązania.  */  std  ::  function  <  void  (  void  )  >  func_d  =  std  ::  bind  (  PrintValue  <  std  ::  string  >  ,  "PI to"  );  func_d  ();  /* Opakowanie funkcji wygenerowane przez std::bind().  * Przekaż parametr podczas wywoływania funkcji.  */  std  ::  function  <  void  (  float  )  >  func_e  =  std  ::  bind  (  PrintValue  <  float  >  ,  std  ::  placeholders  ::  _1  );  func_e  (  3.14159  );  } 

Opakowania funkcji mogą być również używane do uzyskiwania dostępu do zmiennych składowych i funkcji składowych klas.

 
 

  
  
 
      
          
             

   


  
  
   
      
      

  
   
      
  

  
      
      
   

  
     
                                                 
  
 #include  <iostream>  #include  <funkcjonalny>  szablon  <  nazwa typu  T  >  class  CAnyData  {  public  :  CAnyData  (  T  value  )  :  m_value  {  value  }  {}  void  Print  (  void  )  {  std  ::  cout  <<  m_value  <<  std  ::  koniec  ;  }  void  PrintAfterAdd  (  wartość  T  )  {  std  ::  cout  <<  (  m_value  +  value  )  <<  std  ::  endl  ;  }  T  m_wartość  ;  };  int  main  ()  {  /* Opakowanie funkcji zmiennej składowej klasy */  CAnyData  <  int  >  data_a  {  2016  };  std  ::  function  <  int  (  CAnyData  <  int  >  &  )  >  func_a  =  &  CANyData  <  int  >::  m_value  ;  std  ::  cout  <<  func_a  (  data_a  )  <<  std  ::  endl  ;  /* Opakowanie funkcji do funkcji składowej bez przekazywania parametrów */  CAnyData  <  float  >  data_b  {  2016.1  };  std  ::  function  <  void  (  CAnyData  <  float  >  &  )  >  func_b  =  &  CAnyData  <  float  >::  Print  ;  funkcja_b  (  dane_b  );  /* Opakowanie funkcji do funkcji składowej z przekazaniem parametru */  std  ::  function  <  void  (  CAnyData  <  float  >  &  ,  float  )  >  func_c  =  &  CAnyData  <  float  >::  PrintAfterAdd  ;  func_c  (  dane_b  ,  0.1  );  /* Opakowanie funkcji do funkcji składowej wygenerowane przez std::bind */  std  ::  function  <  void  (  float  )  >  func_d  =  std  ::  bind  (  &  CAnyData  <  float  >::  PrintAfterAdd  ,  &  data_b  ,  std  ::  placeholders  : :  _1  );  func_d  (  0.2  );  } 

Linki zewnętrzne