C++ 编译器如何优化模板?

C++ 编译器如何优化模板?,c++,templates,C++,Templates,这样写代码有意义吗 template<bool X> double foo(double x){ return (X) ? moo(x) : bar(x); } 模板 双foo(双x){ 返回(X)?moo(X):bar(X); } 我知道有更好的方法来实现这个例子,但我想知道,假设编译器将识别死代码并将其实例化为 double foo<true>(double x){return moo(x);} double foo<false>(doubl

这样写代码有意义吗

template<bool X>
double foo(double x){
     return (X) ? moo(x) : bar(x);
}
模板
双foo(双x){
返回(X)?moo(X):bar(X);
}
我知道有更好的方法来实现这个例子,但我想知道,假设编译器将识别死代码并将其实例化为

double foo<true>(double x){return moo(x);}
double foo<false>(double x){return bar(x);}
double foo<true>(double x){return moo(x);}
double foo<false>(double x){return bar(x);}
double foo(double x){return moo(x);}
双foo(双x){返回条(x);}
我指定了“noinline”以使其更为明显,我通过cin获得该值,而不是使用常量值以确保编译器不会完全删除该函数。

如您所见,都有各自的功能

true => +0x1780
false => +0x1790

模板函数总是基于模板参数有自己的函数

这里要记住的是模板不同于C#等语言中的泛型等语言功能

将模板视为具有类型意识的高级预处理器是一种相当安全的简化。这就是基本上是编译时编程的思想

与预处理器模板非常相似,模板被展开,结果将经历与常规逻辑相同的所有优化阶段

下面是一个以更符合逻辑的方式重写逻辑的示例。这使用函数专门化

template<bool X>
double foo(double x);

template<>
double foo<true>(double x)
{
    return moo(x);
}

template<>
double foo<false>(double x)
{
    return bar(x);
}
模板
双foo(双x);
模板
双foo(双x)
{
返回moo(x);
}
模板
双foo(双x)
{
返回杆(x);
}
事实上,这是一个令人愉快的意外事件,几乎是所有人的面包和黄油

因此,您可以在编译时进行各种计算

它是惰性评估的,因此您可以通过将无效逻辑放入您不希望使用的模板的专门化中来实现自己的编译时断言。例如,如果我要注释掉
foo
专门化,并尝试像
foo(1.0)那样使用它编译器会抱怨,尽管它对
foo(1.0)非常满意

另一个堆栈溢出帖子演示了这一点

如有兴趣,请进一步阅读:

  • …一般来说,可以安全地假设编译器将识别死机 将其编码并实例化为

    double foo<true>(double x){return moo(x);}
    double foo<false>(double x){return bar(x);}
    
    double foo<true>(double x){return moo(x);}
    double foo<false>(double x){return bar(x);}
    

    “如何”的回答可能有点乏味,但编译器肯定会按照您的预期进行。这是绝对基本的优化。@Columbo所以问题要么太琐碎,要么太宽泛;)然而,我对答案很满意优化与模板关系不大——编译器还将优化
    内联双foo(bool b,double x){return b?moo(x):bar(x);}
    如果它能看到
    b
    @TravisGockel yes的值,但我更愿意让它在代码中可见,因为只有一半的代码是可见的compiled@tobi303我知道你是从哪里来的,但事实上这里不是这样的。条件运算符的两边都是编译的——它们只是碰巧在大多数情况下得到了优化。如果您选择的是无法编译(如:编译器只能看到
    moo(x)
    bar(x)
    ,具体取决于
    x
    ),则可以使用其他技术。如果这是您想要的,我可以提供一个更长的示例。您在<?>括号就是我想说的。在传递给模板的上下文中,它被称为模板参数。问题不是是否会有两个不同的函数,而是如果这两个函数都会有死代码。啊,我完全忽略了这一点,我是以一种低级的心态思考的。编译器显然避免了if(true==true)true_case();您还可以查看我的答案,了解没有重载的版本。C++不允许你部分地使用一个函数模板,但是你可以完全专门化一个函数模板。