运行时函数模板类型推导
Function template type deduction at runtime
尽管模板类型在 运行 时被解析,但我试图理解为什么以下 compiles/runs。是因为 if/else
调用 f
就足以告诉编译器创建 void f<double>(double)
和 void f<std::string>(std::string)
吗?
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
这里没有 运行 时间模板推导。当你有
if(x < 42) f(x);
编译器在编译时知道 x
是一个双精度数,所以它消除了
void f<double>(double)
然后在
else f(std::to_string(x));
编译器知道 std::to_string
的 return 类型是 std::string
,所以它消除了
void f<std::string>(std::string)
使用。这两个函数同时存在,并且在 运行 时间只调用一个函数,具体取决于您为程序提供的输入。
让我们看看this example code provided by chris in his 。使用
#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);
}
使用 -O3 -std=c++1z -Wall -Wextra -pedantic
编译生成程序集
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
如您所见,两个模板函数都存在于程序集中,只是 main 中的 if
决定在 运行 时调用哪一个。
编译器读取 main
,看到对 f
的两次调用,一次使用字符串参数,一次使用 int
生成两个 f
。对这两个函数的调用都嵌入在 main.
中
您的 if 语句导致一个或另一个调用。
所以运行时没有模板解析。这种东西是不存在的
尽管模板类型在 运行 时被解析,但我试图理解为什么以下 compiles/runs。是因为 if/else
调用 f
就足以告诉编译器创建 void f<double>(double)
和 void f<std::string>(std::string)
吗?
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
这里没有 运行 时间模板推导。当你有
if(x < 42) f(x);
编译器在编译时知道 x
是一个双精度数,所以它消除了
void f<double>(double)
然后在
else f(std::to_string(x));
编译器知道 std::to_string
的 return 类型是 std::string
,所以它消除了
void f<std::string>(std::string)
使用。这两个函数同时存在,并且在 运行 时间只调用一个函数,具体取决于您为程序提供的输入。
让我们看看this example code provided by chris in his
#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);
}
使用 -O3 -std=c++1z -Wall -Wextra -pedantic
编译生成程序集
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
如您所见,两个模板函数都存在于程序集中,只是 main 中的 if
决定在 运行 时调用哪一个。
编译器读取
main
,看到对f
的两次调用,一次使用字符串参数,一次使用 int生成两个
f
。对这两个函数的调用都嵌入在 main. 中
您的 if 语句导致一个或另一个调用。 所以运行时没有模板解析。这种东西是不存在的