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?
}
CodePudding user response:
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.
CodePudding user response:
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;
}