2014-06-05 6 views
6

Ich habe eine Frage bezüglich der Funktion Vorlage Parameter Typ Deduktionsprozedur.Braced-Init-Listen und Funktion Vorlagentyp Abzug Auftrag

Nehmen Sie dieses Beispiel:

#include <vector> 
#include <sstream> 
#include <string> 
#include <iterator> 
#include <fstream> 

int main() 
{ 
    std::ifstream file("path/to/file"); 
    std::vector<int> vec(std::istream_iterator<int>{file},{}); // <- This part 
    return 0; 
} 

Wenn ich die Dinge richtig zu verstehen, der zweite Parameter abgeleitet ist vom Typ sein std::istream_iterator von denen der Standard-Konstruktor aufgerufen wird.

Der geeignete std::vector Konstruktor wird als deklariert: der zweite Parameter als std::istream_iterator<int> abgeleitet wird, abgeleitet als auch std::istream_iterator<int>

template <class InputIterator> 
     vector (InputIterator first, InputIterator last, 
       const allocator_type& alloc = allocator_type()); 

Da der erste Parametertyp und so die gleichmäßige Initialisierung Semantik angewendet werden kann. Worüber ich keine Ahnung habe ist, in welcher Reihenfolge der Typabzug geschieht. Ich würde wirklich einige Informationen dazu schätzen.

Vielen Dank im Voraus!

+0

Funktioniert es? Wenn ja, muss zuerst der erste abgezogen werden. – Dani

Antwort

9

Lassen Sie sich ein noch einfacheres Beispiel verwenden:

template<class T> 
void foo(T, T); 

foo(42, {}); 

Der Funktionsaufruf hat zwei Argumente:

  • einen prvalue Ausdruck des Typs int (ein Ganzzahlliteral)
  • eine verspannt-init -list{}

Letzteres, {}, kann Teil einer Ausdruckliste sein, aber es ist kein Ausdruck selbst. Eine Ausdrucksliste ist definiert als eine Initialisierungsliste. braced-init-lists haben keinen Typ.

Die Vorlage wird für jeden Funktionsparameter einzeln [temp.deduct.type]/2 vorgenommen. [Temp.deduct.call]/1 Staaten über Art Abzug für einen Funktionsparameter P:

Wenn Referenzen und cv-Qualifikations von P gibt std::initializer_list<P '> für einige P' und das Entfernen von Argument ist eine Initialisierungsliste, dann wird der Abzug stattdessen für jedes Element der Initialisierungsliste durchgeführt, wobei P ' als Funktionsschablonenparameter Typ und das Initialisierungselement als sein Argument genommen wird. Andernfalls bewirkt ein Initialisierungslistenargument , dass der Parameter als nichtdeduzierter Kontext betrachtet wird. [Hervorhebung von mir]

So im Aufruf foo(42, {}); die T nicht aus dem zweiten Argument {} abgeleitet werden. Aus dem ersten Argument kann jedoch auf T geschlossen werden.

Im Allgemeinen können wir T aus mehreren Funktionsparametern ableiten. In diesem Fall müssen die abgeleiteten Typen genau [temp.educt.type]/2 entsprechen. Es gibt kein Problem, wenn der Typ nur von einem Funktionsparameter abgeleitet wird, aber an anderer Stelle (in einem anderen Funktionsparameter, der sich in einem nicht-abgeleiteten Kontext befindet, im Rückgabetyp usw.) verwendet wird. Typabzug kann z.B. wenn ein Vorlagenparameter nicht von beliebigen Funktionsparameter abgeleitet werden kann und nicht explizit festgelegt ist.

Nach Abzug, T wird durch int ersetzt werden, eine Funktion Signatur ähnlich zu produzieren:

void foo<int>(int, int); 

Diese Funktion kann mit den beiden Argumenten 42 und {} aufgerufen werden. Letzterer führt eine Kopierlisten-Initialisierung durch, die zu einer Werte-Initialisierung des zweiten Parameters führt.

+0

Das ist mehr oder weniger wie ich es intuitiv gesehen habe. Danke, dass du alles klar gemacht hast. – Veritas