読者です 読者をやめる 読者になる 読者になる

ゆとりーなの日記

日記的な事を書いて行くと思はれる

-O3すると警告が出る

七対子の聴牌判定を取り敢えず適当にこう書いてみたわけです。

// 戻り値の32bitの中立っているビットの牌が待ち
// 1bit目1m,2bit目9m,3bit目1p...
// 引数は各牌の所持枚数
// kind[0]=1mの枚数,kind[1]=9mの枚数,kind[2]=1pの枚数...
std::uint32_t GetTitoituMati(const std::array<int, 27> &kind) {
  boost::optional<int> mati;
  int i = 0;
  for (const int size : kind) {
    if (size) {
      // 暗刻以上があったらはずれ
      if (size > 2) {
        return 0x0;
      // 孤立牌は待ちの候補
      } else if (size == 1) {
        // 孤立牌が既にあったらはずれ
        if (mati) {
          return 0x0;
        }
        // 待ちを暫定設定
        mati = i;
      }
    }
    ++i;
  }
  // 待ち設定して返す
  return 1 << *mati; // エラー!
}

このコード、-O3と-Wall,-Werrorを付けたらコンパイルが通らなくなります。

エラー: '*((void*)& mati +4)' はこの関数内初期化されずに使用されるかもしれません [-Werror=maybe uninitialized]

-O3つけないと何も言われないので多分最適化で恐ろしいことになってるとかそんな感じなのでしょうが、どうしたらいいんですかね。理論上は該当箇所で未初期化で使うことはない(はず)のですが。
で、色々試してみたのですが

std::uint32_t GetTitoituMati(const std::array<int, 27> &kind) {
  boost::optional<int> mati = boost::none; // 取り敢えず初期化してみた
  int i = 0;
  for (const int size : kind) {
    if (size) {
      if (size > 2) {
        return 0x0;
      } else if (size == 1) {
        if (mati) {
          return 0x0;
        }
        mati = i;
      }
    }
    ++i;
  }
  return 1 << *mati; // エラー!
}
std::uint32_t GetTitoituMati(const std::array<int, 27> &kind) {
  boost::optional<int> mati = boost::none; // 取り敢えず初期化してみた
  int i = 0;
  for (const int size : kind) {
    if (size) {
      if (size > 2) {
        return 0x0;
      } else if (size == 1) {
        if (mati) {
          return 0x0;
        }
        mati = i;
      }
    }
    ++i;
  }
 // 条件演算子かけてみた
  return mati ? 1 << *mati : 0x0; // エラー!
}

全部駄目でした。
まぁ実は有効な値で初期化すると通るようになるので

std::uint32_t GetTitoituMati(const std::array<int, 27> &kind) {
  boost::optional<int> mati = 0; // 取り敢えず初期化してみた
  mati = boost::none; // 有効値じゃいかんので無効値を入れる
  int i = 0;
  for (const int size : kind) {
    if (size) {
      if (size > 2) {
        return 0x0;
      } else if (size == 1) {
        if (mati) {
          return 0x0;
        }
        mati = i;
      }
    }
    ++i;
  }
 // 条件演算子かけてみた
  return mati ? 1 << *mati : 0x0; // エラー!
}

こうするといけるっぽいですが美しくないです。