2017-02-10 2 views
0

Gemäß cplusplus.com, std::transformwendet eine Operation nacheinander auf die Elemente eines (1) oder zwei (2) Bereichs an und speichert das Ergebnis in dem Bereich, der bei result beginnt. Das letzte Argument von std::transform ist im Allgemeinen eine Funktion, die auf den Elementen des ersten Behälters eine Operation tut, aber ich nehme einen Funktor zum Gegenstand haben, wie folgt:Letztes Argument von std :: transform

struct functor { 
    functor(int x) : x(x) {} 
    int operator()(int x1) {return x + x1;} 

    private : 
    int x; 
} 

Dann anstelle einer Funktion, kann ich auch passieren die Instanz von Funktors, wie folgt aus:

vector<int> v1, v2; 
v1.push_back(1); 
v1.push_back(2); 
v2.resize(v1.size()); 
std::transform(v1.begin(), v1.end(), v2.begin(), functor(1)); 

Meine Frage ist, wie weiß der Compiler, ob eine Funktion oder eine Instanz einer Funktor Klasse an die Funktion std::transform weitergegeben? Wenn eine Instanz übergeben wird, was passiert dann intern, wenn die Funktion auf die Elemente des ersten Containers angewendet wird?

+1

Sie können sich eine Beispielimplementierung ansehen, die unter [cppreference] (http://en.cppreference.com/w/cpp/algorithm/transform) präsentiert wird. Es handelt sich um eine Funktionsvorlage, die den Typ eines Funktors ableitet . Während einer semantischen Analysephase kennt ein Compiler die Arten von AST-Knoten und entwickelt einen Funktionsaufrufsyntaxknoten in einen richtigen Knoten/eine richtige Aktion (Aufruf einer Funktion oder Aufruf eines Funktionsaufrufoperators). –

Antwort

3

std::transform ist eine Schablone (gut, zwei Überlastungen für einen oder zwei Eingangsbereiche) Funktion, die mögliche Implementierung für einen Bereich:

template<class InputIt, class OutputIt, class UnaryOperation> 
OutputIt transform(InputIt first1, InputIt last1, OutputIt d_first, 
        UnaryOperation unary_op) 
{ 
    while (first1 != last1) { 
     *d_first++ = unary_op(*first1++); 
    } 
    return d_first; 
} 

und für zwei Bereiche

template<class InputIt1, class InputIt2, 
     class OutputIt, class BinaryOperation> 
OutputIt transform(InputIt1 first1, InputIt1 last1, InputIt2 first2, 
        OutputIt d_first, BinaryOperation binary_op) 
{ 
    while (first1 != last1) { 
     *d_first++ = binary_op(*first1++, *first2++); 
    } 
    return d_first; 
} 

Die Anforderungen an die Letztes Argument ist, dass es eine operator() für Typen hat, die Sie durch Dereferenzierung von bereitgestellten Iteratoren erhalten (dh ihre Argumente und ihr Rückgabetyp sind implizit in sie konvertierbar). Es könnte also einfache Funktion, Lambda oder irgendein Benutzertyp mit einem solchen Operator sein.

Verwandte Themen