We just started learning template meta programming in C++11. As an exercise we wrote a program that outputs the binary representation of an int value. We came up with two possible implementation. The first one uses recursion with enum values whereas the second method uses a constexpr function.
Our expectation was that both implementation results in executables of the same size. However, the first implementation leads to 9064 bytes whereas the second has 9096 bytes. We don't mind the tiny difference in bytes but do not understand what causes the difference.
We compiled the program with GCC 4.8.2 without optimization flag, however, the same results are found the -O2 flag.
#include <iostream>
using namespace std;
template <int val>
struct Bin
{
enum { value = 10 * Bin<(val >> 1)>::value + (val & 1) };
};
template <>
struct Bin<0>
{
enum { value = 0 };
};
constexpr int bin(int val)
{
return val == 0 ? 0 : (10 * bin(val >> 1) + (val & 1));
}
int main()
{
// Option 1
cout << Bin<5>::value << '\n'
<< Bin<27>::value << '\n';
// Option 2
cout << bin(5) << '\n'
<< bin(27) << '\n';
}
constexpr
functions may be evaluated at compile-time. They are not required to.
For the code you provided, the compiler isn't indeed doing that and bin
is getting called at runtime; this means the function cannot be thrown away from the assembly. By explicitly requiring the values to be constexpr
with
constexpr auto i = bin(5), j = bin(27);
the calls to bin
are done at compile-time as shown here. With
cout << bin(5) << '\n'
<< bin(27) << '\n';
the relevant emitted code is
movl $5, %edi # Parameter
callq bin(int) # Here's the call to bin
movl std::cout, %edi
movl %eax, %esi
callq std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
[...]
movl $27, %edi # parameter
callq bin(int) # call to bin
movq %rbx, %rdi
movl %eax, %esi
callq std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
When the call is elided, the size is the same for both versions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With