2017-04-27 18 views
3

実行時にテンプレートタイプが解決されているにもかかわらず、以下のコンパイル/実行がなぜ発生するのか理解しようとしています。コンパイラにvoid f<double>(double)void f<std::string>(std::string)を作成するように指示するのに、fだけを呼び出すのはif/elseで十分ですか?実行時の関数テンプレートタイプの控除

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

ifおよびelseブランチの両方に対してコードが生成されます。実行時に、 'x'の値に応じて適切なブランチが実行されます。 –

答えて

8

ここで起こって何の実行時にテンプレート控除はありません。あなたはコンパイラがその後スタンプアウト

void f<double>(double) 

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

コンパイラはの戻り値の型を知っているので、xは、二重であることを、コンパイル時に、知っている

if(x < 42) f(x); 

を持っている場合std::to_stringstd::stringなので、それはスタンプアウトです

void f<std::string>(std::string) 

使用する。両方の関数が同時に存在し、プログラムに与える入力に応じて実行時に呼び出されるのは1つだけです。

chriscommentで提供されるthis example codeを見てください。あなたは両方のテンプレート関数は、アセンブリ内に存在し、それが実行時に呼び出すするかを決定し、メインでちょうどifで見ることができるよう-O3 -std=c++1z -Wall -Wextra -pedanticしてコンパイル

#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); 
} 

を使用すると、アセンブリ

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 

を生成します。

+2

説明のために、 ''と ''の膨らみのない例のアセンブリを見ることができます:https://godbolt.org/g/p2oF34 – chris

+0

@chris良い例です。それを私の答えに加えていくつか見せてもらえますか? – NathanOliver

+1

まったく、SOはコミュニティの努力です。 – chris

1
  1. コンパイラは、mainを読みfには、2つの呼び出しを見て、一度文字列引数を持つと一度int型

  2. を持つ2つのf Sを生成します。両方の関数の呼び出しはmainに組み込まれています。

  3. ifステートメントは、1回または別の呼び出しを行います。 したがって、実行時にテンプレート解決はありません。そんなものは存在しない。

関連する問題