c++ - 使用 constexpr 或 struct 进行元编程

标签 c++ c++11 template-meta-programming constexpr

我们刚刚开始学习 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 with

constexpr auto i = bin(5), j = bin(27);

bin 的调用在编译时完成,如图所示 here .与

  cout << bin(5) << '\n'
      << bin(27) << '\n'; 

相关的发射代码是

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)

当调用被省略时,两个版本的大小相同。

关于c++ - 使用 constexpr 或 struct 进行元编程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32007987/

相关文章:

c++ - C++ 队列中的线程池

c++ - 为什么 std::copy_n 不增加输入迭代器 n 次?

c++ - 如何在 C++ 编译时实现有向无环图 DAG

c++ - Expand Variadic Template in Vardiadic Macro(如何从目标函数中提取参数名称)

c++ - 我需要什么类型的类(class)?

c++ - gettext - 加载本地目录

c++ - Typedef数组指针参数的C++ ostream重载

c++11 - 新的现代 C++ 容器中的分配器传播策略

c++ - 如何在 boost::msm 中实现可访问状态机 (SM) 后端/前端的 "BaseState"

c++ - 我可以用逗号声明多个函数吗?