FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

C++11でのusingとenum classについての調査

出張で飛行機に乗っている間、久しぶりにC++の本を開いて、自分の知らないC++の使い方について調査していたのだが、C++11の新機能として、いろいろと簡単に書き換えられそうなものがある。

Effective Modern C++ ―C++11/14プログラムを進化させる42項目

Effective Modern C++ ―C++11/14プログラムを進化させる42項目

自作ISSのコードについては、C++11の対応を進めてきたつもりだ。例えば、スマートポインタの導入や、autoを使ったSTLコンテナの探索を記述簡略化などを進めてきた。

今回導入するのは、typedefの代わりにusingを使い、enumの代わりにenum classを導入するということだ。 どちらも、現状のISSにおいて導入しても、明確な利点が現れるわけではないのだが、今後のために導入しておこう。

C++11のusingについて

C++11のusingは、typedefに置き換わるものらしい。非常に簡単なケースでいうと、以下のような書きかえを行った。

github.com

-typedef std::vector<FunctionInfo *> FunctionTable;
+using FunctionTable = std::vector<FunctionInfo *>;

このようにする。これで、typedefを置き換えることができる。 これだけだと、明確な利点が存在していないように見えるが、usingを使うことにより、テンプレート化をすることが利点だ。

template<typename T>
using MyAllocList = std::list<T, MyAlloc<T>>;
MyAllocList<Widget> lw;

C++11のenum classについて

これも、enumに取って代わるものだ。非常に簡単なケースでいうと、以下のような書き換えを行った。

github.com

enum class PrivMode {
  PrivUser       = 0,
  PrivSupervisor = 1,
  PrivHypervisor = 2,
  PrivMachine    = 3
};

...

  switch (curr_priv) {
  case PrivMode::PrivUser     : {
...
  case PrivMode::PrivSupervisor : {
...
  case PrivMode::PrivHypervisor : {
...

これにより、enumで定義したものはクラスとして定義され、明確の型として宣言されることになる。したがって、これらの定数を数値として扱うためには、それらを明示的に変換する必要がある。

enum class ExceptCode {
  Except_InstAddrMisalign = 0,
  Except_InstAccessFault  = 1,
  Except_IllegalInst    = 2,
  Except_Breakpoint     = 3,
  Except_LoadAddrMisalign = 4,
...

  if (code == ExceptCode::Except_InstAddrMisalign) {
    epc = GetPreviousPC ();
...
    SetPrivMode (PrivMode::PrivMachine);
    CSRWrite (SYSREG_ADDR_MEPC,   epc);
    CSRWrite (SYSREG_ADDR_MCAUSE,   static_cast<Word_t>(code));

    SetPC (0x00000100);
    SetJumped (true);

codeは、ExceptCode型として定義されているので、Word_tに変換した上でレジスタへの書き込みを実行する、という訳だ。 いちおう、これらの書き換えを行って、リグレッションテストを行った。問題なしだ。