LoginSignup
4
2

More than 5 years have passed since last update.

C++のコンパイル時に型を使った自然数で1+1==2を確かめる

Last updated at Posted at 2018-08-24

小ネタ. (0 = zero, 1 = succ<zero>, 2 = succ<succ<zero>>, ...)という風にネストしたクラステンプレートの実体を自然数に対応させて1+1=2を確認する. 数学に疎いので厳密な証明になっているかはわかりません.

#include <type_traits>

namespace nat {
struct nat {};

template <class T>
concept bool Nat = std::is_base_of_v<nat, T>;

/* 自然数0が存在する */
struct zero : nat {};

/* 全ての自然数にはその次の自然数が存在する */
template <Nat>
struct succ : nat {};

template <Nat, Nat>
struct plus;

template <Nat N, Nat M>
using plus_t = typename plus<N, M>::type;

/* 加法の定義 */
/* N + 0 = N */
template <Nat N>
struct plus<N, zero> {
  using type = N;
};

/* 加法の定義 */
/* N + succ(M) = succ(N + M) */
template <Nat N, Nat M>
struct plus<N, succ<M>> {
  using type = succ<plus_t<N, M>>;
};

} // namespace nat

auto main() -> int {
  using namespace nat;

  /* 1 := succ(0) */
  using one = succ<zero>;

  /* 2 := succ(succ(0)) */
  using two = succ<succ<zero>>;

  static_assert(std::is_same_v<plus_t<one, one>, two>, "1 + 1 == 2");
}

検証(コンパイル)

自然数の制約にC++2aのconceptを使ったので適宜対応するオプションを与える. アサーションが失敗せずにコンパイルが通るはず.

$ g++-8 -std=c++2a -fconcepts peano.cpp

おまけ

偶数を定義してみる

namespace nat {
template <Nat>
struct is_even;

template <Nat N>
constexpr bool is_even_v = is_even<N>::value;

template <Nat N>
concept bool Even = is_even_v<N>;

/* 0は偶数 */
template <>
struct is_even<zero> : public std::bool_constant<true> {};

/* 偶数の次の次は偶数 */
template <Even E>
struct is_even<succ<succ<E>>> : public std::bool_constant<true> {};

/* それ以外は偶数ではない */
template <Nat>
struct is_even : public std::bool_constant<false> {};
} // namespace nat

auto main() -> int {
  using namespace nat;
  using one = succ<zero>;
  using two = succ<one>;
  using three = succ<two>;
  using four = succ<three>;
  using five = succ<four>;

  static_assert(Even<zero>,   "0 is even");
  static_assert(!Even<one>,   "1 is not even");
  static_assert(Even<two>,    "2 is even");
  static_assert(!Even<three>, "3 is not even");
  static_assert(Even<four>,   "4 is even");
  static_assert(!Even<five>,  "5 is not even");
}
4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2