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

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

本文关键字:lt gt 条件 same 评估 编译 is 是否 std      更新时间:2023-10-16

我知道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保证在编译时进行评估,但是我只是想知道在这种情况下是否可以在编译时间进行评估,因为从is_same返回的boolconstexpr。例如在无法使用C 17的情况下。

考虑代码的此稍微修改的版本(以便控制流无法达到这种非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    $40, %esp
    movl    48(%esp), %ebx
    leal    31(%esp), %eax
    movl    $LC0, 4(%esp)
    movl    %eax, 8(%esp)
    movl    %ebx, (%esp)
    call    __ZNSsC1EPKcRKSaIcE
    addl    $40, %esp
    movl    %ebx, %eax
    popl    %ebx
    ret $4

上面的代码中没有任何条件。

因此,对于此编译器和平台,实际上在编译时评估了条件。您可以针对目标编译器和平台类似地进行。

如果要确定,请检查生成的程序集。但是,很有可能编译器确实会通过无条件的return替换if(如果Tfloatdouble(,或完全将其删除(否则(。这是一个相当基本的优化。

您将需要确保T的所有代码路径为floatdouble,而其他代码路径则需要同时有效,以使其编译。如果ifelse中的代码对特定类型无效,则遇到错误。

为了进行精确的优化,您需要检查装配代码。