使用 constexpr 或 struct 进行元编程
Metaprogramming with constexpr or struct
我们刚刚开始学习 C++11 中的模板元编程。作为练习,我们编写了一个输出 int 值的二进制表示的程序。我们提出了两种可能的实现方式。第一个使用带有枚举值的递归,而第二个方法使用 constexpr 函数。
我们的期望是两种实现都产生相同大小的可执行文件。然而,第一个实现导致 9064 字节,而第二个实现有 9096 字节。我们不介意字节数的微小差异,但不了解导致差异的原因。
我们使用没有优化标志的 GCC 4.8.2 编译程序,但是,在 -O2 标志下发现了相同的结果。
#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
函数 可能 在编译时计算。他们不需要。
对于您提供的代码,编译器实际上并没有这样做,bin
是在运行时被调用;这意味着该功能不能从程序集中丢弃。通过明确要求值是 constexpr
和
constexpr auto i = bin(5), j = bin(27);
对 bin
的调用是在编译时完成的,如 here 所示。随着
cout << bin(5) << '\n'
<< bin(27) << '\n';
相关的发射代码是
movl , %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 , %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)
省略调用后,两个版本的大小相同。
我们刚刚开始学习 C++11 中的模板元编程。作为练习,我们编写了一个输出 int 值的二进制表示的程序。我们提出了两种可能的实现方式。第一个使用带有枚举值的递归,而第二个方法使用 constexpr 函数。
我们的期望是两种实现都产生相同大小的可执行文件。然而,第一个实现导致 9064 字节,而第二个实现有 9096 字节。我们不介意字节数的微小差异,但不了解导致差异的原因。
我们使用没有优化标志的 GCC 4.8.2 编译程序,但是,在 -O2 标志下发现了相同的结果。
#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
函数 可能 在编译时计算。他们不需要。
对于您提供的代码,编译器实际上并没有这样做,bin
是在运行时被调用;这意味着该功能不能从程序集中丢弃。通过明确要求值是 constexpr
和
constexpr auto i = bin(5), j = bin(27);
对 bin
的调用是在编译时完成的,如 here 所示。随着
cout << bin(5) << '\n'
<< bin(27) << '\n';
相关的发射代码是
movl , %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 , %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)
省略调用后,两个版本的大小相同。