可以在编译时评估使用 std::is_same<> 的条件吗?

Can this condition using std::is_same<> be evaluated at compile time?

我知道 constexpr 函数不必在编译时求值,但如果可能的话它们会被求值。以下if的条件是否在编译时求值?

template <typename T> inline std::string toString(const T& arg, int decPlaces) 
{ 
    if (!std::is_same<T, float>::value && !std::is_same<T, double>::value)
        return std::to_string(arg);
    // Else go on strip digits after decimal point
}

我知道在 C++17 中有 if constexpr 保证在编译时求值,但我只是想知道在这种情况下是否可以在编译时求值,因为 boolis_same 返回的是 constexpr。比如不能使用C++17的情况。

如果您想确定,请检查生成的程序集。但是,编译器极有可能确实会用无条件的 return 替换 if(如果 Tfloatdouble),或者删除它完全(否则)。这是一个相当基本的优化。

您需要确保 T 的所有代码路径为 floatdouble,其他代码路径需要同时有效才能编译。如果 ifelse 中的代码对特定类型无效,您 运行 就会出错。

对于应用的确切优化,您需要检查汇编代码。

考虑一下你的代码的这个稍微修改的版本(这样控制流就不能到达这样一个非void函数的结尾):

template <typename T> inline std::string toString(const T& arg, int decPlaces) 
{ 
    if (!std::is_same<T, float>::value && !std::is_same<T, double>::value)
        return std::to_string(arg);

    return ""; // <-- added
}

通过显式实例化 T=float 的模板函数:

template std::string toString<float>(const float&, int);

然后在启用g++6.4.0-O2的情况下进行编译,为x86生成以下汇编代码 平台:

__Z8toStringIfESsRKT_i:
    pushl   %ebx
    subl    , %esp
    movl    48(%esp), %ebx
    leal    31(%esp), %eax
    movl    $LC0, 4(%esp)
    movl    %eax, 8(%esp)
    movl    %ebx, (%esp)
    call    __ZNSsC1EPKcRKSaIcE
    addl    , %esp
    movl    %ebx, %eax
    popl    %ebx
    ret 

上面的代码中没有条件

所以,对于这个编译器和平台,条件实际上是在编译时评估的。您可以针对您的目标编译器和平台进行类似的操作。