2017-04-27 4 views
3

Ich versuche zu verstehen, warum die folgenden Kompilierungen/Läufe trotz der Vorlage zur Laufzeit aufgelöst werden. Ist es, weil die if/else Aufrufe an f allein genug sind, um dem Compiler zu sagen, void f<double>(double) und void f<std::string>(std::string) zu erstellen?Funktion Vorlagentyp Abzug zur Laufzeit

test.hpp

#include <type_traits> 
#include <string> 
#include <iostream> 

template <typename T> 
void f(T x) { 
    if(std::is_same<T, std::string>::value) 
     std::cout << "String: " << x; 
} 

test.cpp

#include <iostream> 
#include "test.hpp" 

int main(int, char** argv) { 
    double x(std::stod(argv[1])); 

    if(x < 42) f(x); 
    else f(std::to_string(x)); 

    return 0; 
} 

$ (clan)g++ -std=c++14 test.cpp 
$ ./a.exe 41 

$ ./a.exe 43 
String: 43.000000 
+1

Code wird sowohl für die Zweige if als auch else generiert. Zur Laufzeit wird der entsprechende Zweig in Abhängigkeit vom Wert von x ausgeführt. –

Antwort

8

Es gibt keine hier los Vorlage Abzug Laufzeit. Wenn Sie

if(x < 42) f(x); 

Der Compiler weiß, bei der Kompilierung, dass x eine doppelt so hoch ist, so dass es Briefmarken aus

void f<double>(double) 

Dann in

else f(std::to_string(x)); 

Der Compiler den Rückgabetyp von weiß std::to_string ist ein std::string so stempelt es eine

aus

Zu verwenden. Beide Funktionen existieren gleichzeitig und nur einer wird zur Laufzeit aufgerufen, je nachdem, welche Eingabe Sie dem Programm geben.

Lets Blick auf this example code von chris in seiner comment zur Verfügung gestellt.

#include <type_traits> 

template <typename T> 
__attribute__((used)) int f(T x) { 
    if(std::is_same<T, int>::value) 
     return 1; 
    else 
     return 2; 
} 

int main(int argc, char** argv) { 
    if(argc > 1) return f(1); 
    else return f(1.0); 
} 
Mit

mit -O3 -std=c++1z -Wall -Wextra -pedantic Kompilieren erzeugt die Baugruppe

main:         # @main 
     xor  eax, eax 
     cmp  edi, 2 
     setl al 
     inc  eax 
     ret 

int f<int>(int):      # @int f<int>(int) 
     mov  eax, 1 
     ret 

int f<double>(double):     # @int f<double>(double) 
     mov  eax, 2 
     ret 

, wie Sie beide Vorlage sehen können Funktionen in der Baugruppe vorhanden sind, und es ist nur die if in Haupt, die entscheidet, welche man zur Laufzeit nennen.

+2

Zu Illustrationszwecken können Sie die Assembly eines Beispiels ohne die Aufblähung '' und '' betrachten: https://godbolt.org/g/p2oF34 – chris

+0

@chris Nettes kleines Beispiel.Darf ich das meiner Antwort hinzufügen, um es zu zeigen? – NathanOliver

+1

Überhaupt nicht, SO ist eine Gemeinschaftsbemühung. – chris

1
  1. Compiler main liest, sieht zwei Anrufe f, einmal mit einem String-Argument und einmal mit einem int

  2. Erzeugt zwei f s. Aufrufe an beide Funktionen sind in main eingebettet.

  3. Ihre if-Anweisung verursacht den einen oder anderen Anruf. Es gibt also keine Template-Auflösung in Runtime. So etwas gibt es nicht.