运行时的函数模板类型推导

Alm*_*ely 3 c++ templates runtime function compile-time

我试图理解为什么以下编译/运行尽管在运行时解析模板类型.是因为单独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;
}
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)
$ (clan)g++ -std=c++14 test.cpp
$ ./a.exe 41

$ ./a.exe 43
String: 43.000000
Run Code Online (Sandbox Code Playgroud)

Nat*_*ica 8

这里没有运行时模板扣除.当你有

if(x < 42) f(x);
Run Code Online (Sandbox Code Playgroud)

编译器在编译时知道它x是一个双精度因此它会被标记出来

void f<double>(double)
Run Code Online (Sandbox Code Playgroud)

然后进去

else f(std::to_string(x));
Run Code Online (Sandbox Code Playgroud)

编译器知道返回类型std::to_string是一个,std::string所以它标记了一个

void f<std::string>(std::string)
Run Code Online (Sandbox Code Playgroud)

使用.这两个函数同时存在,并且在运行时只调用一个函数,具体取决于您为程序提供的输入.

让我们看看chris在他的评论中提供的这个示例代码.运用

#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);
}
Run Code Online (Sandbox Code Playgroud)

编译时会-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
Run Code Online (Sandbox Code Playgroud)

正如您所看到的那样,程序集中存在两个模板函数,并且它只是if在main中决定在运行时调用哪个函数.

  • 为了便于说明,您可以查看一个示例的程序集,其中没有"<iostream>"和"<string>"的膨胀:https://godbolt.org/g/p2oF34 (2认同)