2012-04-04 12 views
1

Wie lautet die Form (falls vorhanden), um Template-Funktionen zu schreiben, wobei Argumente Template-Container sind?Typ-Inferenz für Template-Funktionen mit Template-Parametern

Zum Beispiel möchte ich eine generische Summe schreiben, die auf jedem Container funktioniert, der iteriert werden kann. Bei dem folgenden Code muss ich zum Beispiel sum<int>(myInts) schreiben. Ich würde es vorziehen, einfach sum(myInts) und den Typ zu schreiben, der von dem Typ abgeleitet werden soll, den myInts enthält.

/** 
@brief Summation for iterable containers of numerical type 
@tparam cN       Numerical type (that can be summed) 
@param[in] container    container containing the values, e.g. a vector of doubles 
@param[out] total     The sum (i.e. total) 
*/ 
template<typename N, typename cN> 
N sum(cN container) { 
    N total; 
    for (N& value : container) { 
     total += value; 
    } 
    return total; 
} 
+2

Sie wissen, dass 'std :: accumum' für Das? – jrok

Antwort

0

Dies, auch wenn umständlich, 11 ++ den Trick in C tun:

template <typename C> 
auto sum(C const & container) 
    -> std::decay<decltype(*std::begin(container))>::type 

Eine weitere Option ist nur die gleiche Struktur verwenden, die akkumulieren tut: haben die Aufrufer übergeben ein zusätzliches Argument mit dem Anfangswert und verwenden Sie das, um das Ergebnis des Ausdrucks zu steuern:

(Durch die Angabe eines Vorschlagswerts kann der Benutzer entscheiden, ihn mit einem Wert aufzurufen oder das Template-Argument anzugeben - aber dafür muss der Typ N als Standardkonstrukt definiert sein)

+0

Was ist der Pfeil hier? Ist es der gleiche Pfeil, der in der Lambda-Notation verwendet wird? – zenna

+1

@zenna: Es ist die Syntax, um den abschließenden Rückgabetyp zu liefern, und ja, es erfüllt den gleichen Zweck wie in einem Lambda: '[] (int x) -> double {return 3 * x; } ' –

+0

Aus irgendeinem Grund ist declltype (* std :: begin (container)) eine Referenz (ich nehme an ints). – zenna

3

Ich schreibe eine solche Funktion wie dieses

template<typename IT1> 
typename std::iterator_traits<IT1>::value_type //or decltype! 
function(IT1 first, const IT1 last) 
{ 
    while(first != last) 
    { 
     //your stuff here auto and decltype is your friend. 
     ++first; 
    } 
    return //whatever 
} 

Auf diese Weise wird es nicht nur mit mehr arbeiten Behältern, zB Ostream Iteratoren und Verzeichnis Iteratoren.

Anruf wie

function(std::begin(container), std::end(container)); 
Verwandte Themen