Zebrafish
Zebrafish

Reputation: 13876

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

I know that constexpr functions don't have to be evaluated at compile time, but they are if it is possible. Is the condition of the following if evaluated at compile time or not?

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
}

I know that in C++17 there is if constexpr which guarantees evaluation at compile time, but I'm just wondering whether it might be evaluated at compile time in this case because the bool returned from is_same is constexpr. Such as in a situation when C++17 cannot be used.

Upvotes: 3

Views: 4927

Answers (3)

jfMR
jfMR

Reputation: 24738

Consider this slightly modified version of your code (so that the control flow cannot reach the end of such a non-void function):

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
}

By explicitly instantiating your template function for T=float:

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

and then compiling it with g++ 6.4.0 and -O2 enabled, the following assembly code is generated for the x86 platform:

__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

There is nothing conditional in the code above.

So, for this compiler and platform, the condition is actually evaluated at compile time. You can proceed analogously for your targeted compiler and platform.

Upvotes: 4

Niall
Niall

Reputation: 30605

You will need to make sure all code paths for T being float or double and others will need to be valid at the same time for it to compile. If the code in the if and else would not be valid for a specific type, you run into errors.

For the exact optimisations applied, you would need to inspect the assembly code.

Upvotes: 0

If you want to be sure, inspect the generated assembly. However, it's extremely that likely the compiler will indeed replace the if by an unconditional return (if T is a float or double), or remove it altogether (otherwise). This is a fairly basic optimisation.

Upvotes: 0

Related Questions