本当は怖いHPC

HPC屋の趣味&実益ブログ

C++11でmax/min/powをコンパイル時計算

C++11のconstexprを使うと、従来は実行時のみに限定されていた定数計算をコンパイル時に行うことができる。これによって、例えば配列の引数にmin/max/階乗等の計算を用いることができる。

pow()の例は、Effective Modern C++のItem 15で解説されている。

Effective Modern C++: 42 Specific Ways to Improve Your Use of C++11 and C++14

Effective Modern C++: 42 Specific Ways to Improve Your Use of C++11 and C++14

min/maxについては、Lisp風に可変長引数を取れるようにしてある。

#include<iostream>

template<class T> constexpr T smax(T a) noexcept {
  return a;
}

template<class T> constexpr T smax(T a, T b) noexcept {
  return a > b ? a : b;
}

template<class T, class ... Args>
constexpr T smax(T a, T b, Args ... args) noexcept {
  return smax(a, smax(b, args...));
}

template<class T> constexpr T smin(T a) noexcept {
  return a;
}

template<class T> constexpr T smin(T a, T b) noexcept {
  return a > b ? b : a;
}

template<class T, class ... Args>
constexpr T smin(T a, T b, Args ... args) noexcept {
  return smin(a, smin(b, args...));
}

template<class T>
constexpr T spow(T base, T exp) noexcept {
  //static_assert(exp >= 0, "Exponent must not be negative");
  return exp <= 0 ? 1
      :  exp == 1 ? base
      :  base * spow(base, exp-1);
}

int main() {
  int foo[ smax(spow(2,5),
                smax(5,2,3)) ];
  std::cout << "int foo[" << (sizeof(foo) / sizeof(foo[0])) << "]" << std::endl;

  return 0;
}

実行結果:

$ clang++ -std=c++11 static_minmax.cpp && ./a.out
int foo[16]
【広告】