Funktionell (C++)
C++ standardbibliotek |
---|
Behållare |
C standardbibliotek |
I sammanhanget med programmeringsspråket C++ hänvisar funktionell
till en rubrikfil som är en del av C++ Standard Library och tillhandahåller en uppsättning fördefinierade klassmallar för funktionsobjekt , inklusive operationer för aritmetik, jämförelser och logik. Förekomster av dessa klassmallar är C++-klasser som definierar en funktionsanropsoperatör , och förekomsterna av dessa klasser kan anropas som om de vore funktioner . Det är möjligt att utföra mycket sofistikerade operationer utan att skriva ett nytt funktionsobjekt, helt enkelt genom att kombinera fördefinierade funktionsobjekt och funktionsobjektadaptrar.
Klassmallen std::funktion
som tillhandahålls av C++11 är en polymorf funktionsomslag för allmänt ändamål . Förekomster av std::function
kan lagra, kopiera och anropa alla anropbara mål—funktioner, lambda-uttryck (uttryck som definierar anonyma funktioner ), binda uttryck (instanser av funktionsadaptrar som omvandlar funktioner till andra funktioner med mindre aritet genom att tillhandahålla värden för några av argumenten), eller andra funktionsobjekt.
Algoritmerna som tillhandahålls av C++ Standard Library kräver inte funktionsobjekt med fler än två argument . Funktionsobjekt som returnerar booleska värden är ett viktigt specialfall. En unär funktion vars returtyp är bool
kallas ett predikat och en binär funktion vars returtyp är bool
kallas ett binärt predikat .
Anpassningsbara funktionsobjekt
I allmänhet har ett funktionsobjekt begränsningar för typen av dess argument. Typbegränsningarna behöver dock inte vara enkla: operatören ()
kan vara överbelastad eller kan vara en medlemsmall. På samma sätt behöver det inte finnas något sätt för ett program att avgöra vilka dessa begränsningar är. Ett anpassningsbart funktionsobjekt anger dock vad argument- och returtyperna är och tillhandahåller kapslade typedef
s så att dessa typer kan namnges och användas i program. Om en typ F0
är en modell av en anpassningsbar generator, måste den definiera F0 :: result_type
. På liknande sätt, om F1
är en modell av den anpassningsbara unära funktionen måste den definiera F1 :: argument_type
och F1 :: result_type
, och om F2
är en modell av den anpassningsbara binära funktionen måste den definiera F2 :: first_argument_type
, F2 :: second_argument_type
, och F2 :: resultattyp
. C++ Standard Library tillhandahåller basklasser unary_function
och binary_function
för att förenkla definitionen av anpassningsbara unära funktioner och anpassningsbara binära funktioner.
Anpassningsbara funktionsobjekt är viktiga eftersom de kan användas av funktionsobjektadaptrar: funktionsobjekt som transformerar eller manipulerar andra funktionsobjekt. C++ Standard Library tillhandahåller många olika adaptrar för funktionsobjekt, inklusive unary_negate
(som returnerar det logiska komplementet av värdet som returneras av ett visst anpassningsbart predikat), och unary_compose
och binary_compose
, som utför sammansättningen av funktionsobjektet.
Fördefinierade funktionsobjekt
C++ Standard Library inkluderar i huvudfilens funktionella många
olika fördefinierade funktionsobjekt, inklusive aritmetiska operationer ( plus
, minus
, multiplicerar
, dividerar
, modul
och negera
), jämförelser ( lika_till
, inte_lika_till
, större
, mindre
, större_lika
och mindre lika
), och logiska operationer ( logical_and
, logical_or
, och logical_not
).
Exempel
Funktionsomslag kan användas för att göra anrop till vanliga funktioner eller till funktionsobjekt skapade av lambda-uttryck.
#inkludera <iostream> #inkludera <funktionell> /* Definiera en mallfunktion */ mall < typnamn T > void PrintValue ( T värde ) { std :: cout << värde << std :: endl ; } int main ( void ) { /* Ett funktionsomslag till en funktion */ std :: function < void ( int ) > func_a = PrintValue < int > ; func_a ( 2015 ); /* Ett funktionsomslag till en funktionspekare */ std :: function < void ( int ) > func_b = & PrintValue < int > ; func_b ( 2016 ); /* Ett funktionsomslag till en lambdafunktion. */ std :: function < void ( int ) > func_c = []( int value ) { std :: cout << värde << std :: endl ; }; func_c ( 2017 ); /* Ett funktionsomslag genererat av std::bind(). * Skicka en fördefinierad parameter vid bindning. */ std :: function < void ( void ) > func_d = std :: bind ( PrintValue < std :: string > , "PI is" ); func_d (); /* Ett funktionsomslag genererat av std::bind(). * Skicka en parameter när funktionen anropas. */ std :: function < void ( float ) > func_e = std :: bind ( PrintValue < float > , std :: platshållare :: _1 ); func_e ( 3,14159 ); }
Funktionsomslag kan också användas för att komma åt medlemsvariabler och medlemsfunktioner i klasser.
#inkludera <iostream> #inkludera <funktionell> mall < typnamn T > klass CAnyData { public : CAnyData ( T värde ) : m_värde { värde } {} void Print ( void ) { std :: cout << m_value << std :: endl ; } void PrintAfterAdd ( T värde ) { std :: cout << ( m_värde + värde ) << std :: endl ; } T m_värde ; }; int main () { /* Ett funktionsomslag till en medlemsvariabel i en klass */ CAnyData < int > data_a { 2016 }; std :: funktion < int ( CAnyData < int > & ) > func_a = & CAnyData < int >:: m_value ; std :: cout << func_a ( data_a ) << std :: endl ; /* Ett funktionsomslag till medlemsfunktion utan att parametern skickar */ CAnyData < float > data_b { 2016.1 }; std :: function < void ( CAnyData < float > & ) > func_b = & CAnyData < float >:: Skriv ut ; func_b ( data_b ); /* En funktionsomslutning till medlemsfunktion med överföring av en parameter */ std :: function < void ( CAnyData < float > & , float ) > func_c = & CAnyData < float >:: PrintAfterAdd ; func_c ( data_b , 0,1 ); /* En funktionsomslutning till medlemsfunktion genererad av std::bind */ std :: function < void ( float ) > func_d = std :: bind ( & CAnyData < float >:: PrintAfterAdd , & data_b , std :: platshållare : : _1 ); func_d ( 0,2 ); }