简体   繁体   中英

constexpr and template compile time?

I have a few questions. I'm confused with template and constexpr and the difference.

I know templates are instantiated at compile time are they executed at compile time or only in run time? Is there a example where I can use them together to get some benefit?

And what is happening if we have a template with constexpr like in this example.

template <typename T>
constexpr T get_sum(T a, T b)
{
    return a+b;
}

int main()
{
    constexpr int a = get_sum(2,3); // compile time?
    const float b = get_sum(2.2,3.2); // compile time?
    float c = get_sum(2.2,3.2); // run time?
}

Your get_sum is a function template. get_sum<int> is a function almost like any other function. Don't get confused by template argument deduction, which does happen at compile time. Without deduction your main is exactly the same as:

constexpr int a=get_sum<int>(2,3);
const float b=get_sum<double>(2.2,3.2);
float c=get_sum<double>(2.2,3.2);

In a nutshell, templates get instantiated by the compiler when needed. Once the compiler synthesized a function, eg get_sum<int> this is a function like other functions and whether the function is constexpr is orthogonal to whether it is the result of instantiating a template.

constexpr on a function tells the compiler that the function can be evaluated at compile time. The compiler must evaluate it at compile time when called in a constexpr context. For example constexpr int a is initialized at compile time. A const float might be initilized already by the compiler. Even a (non-const) float might be optimized away completely by the compiler. There is nothing that prevents a compiler to optimize something as long as the observable behvior of the program is the same (none of your 3 variables is actually used).

Ergo:

int main()
{
    constexpr int a=get_sum(2,3);    // get_sum<int> must be called at compile time
    const float b=get_sum(2.2,3.2);  // get_sum<double> is likely to be called at compile time
    float c=get_sum(2.2,3.2);        // get_sum<double> might be called at compile time or runtime
                                     // or not at all, because the call does not 
                                     // contribute to observable behavior
}

TL;DR

Whether a function is an intantiation of a function template and whether the function is constexpr are orthogonal.

For constexpr's there is also static_assert. constexpr can be used both at compile time and runtime. (C++20 has consteval, which only allows for compile time evaluation).

#include <cassert>

template<typename type_t>
constexpr auto sum(const type_t& value1, const type_t& value2)
{
    return value1 + value2;
}

int main()
{
    constexpr auto constexpr_value = sum(1, 2); // <== compile time
    static_assert(constexpr_value == 3); // <== compile time validation

    // or shorter
    static_assert(sum(1, 2) == 3); // <== compile time evaluation

    // constexpr's also can compile to runtime versions
    
    auto value = sum(2, 3); // <== runtime evaluation
    assert(value == 5);

    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM