2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Qt4をgcc9でコンパイルすると、foreach文が1回しかループを反復しなくなる

Posted at

Ubuntu18では正常に動いていたアプリケーションがあったのですが、OSのバージョンアップが必要になったため、Ubuntu20の環境でビルド・動作確認を実施。

すると、今までパスしていたテストが通らなくなってしまったので、色々と調査したところ、コンテナのサイズに関係なく、Qtのforeach文が1回分しかループを回していないという事実が判明しました。

Qtのforeach文はマクロ定義されていて、C++11以降で使えるようになった拡張for文とほぼ同じような感覚で使えます。

QList<qint32> qList;
qList << 1;
qList << 2;
qList << 3;
qList << 4;

foreach (qint32 val, qList)
{
    std::cout << val;
}

通常であれは「1234」の出力が期待できますが、「1」しか出力されないというのが今回起きた事象です。

調べてみたところ、どうやら同じ事象がstack overflowで話題に上がっているようでした。
https://stackoverflow.com/questions/61635549/qt-foreach-only-iterates-once-ignoring-the-rest-of-the-items

バグレポートとしても上がっているようです。
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90617

どうやらfor文の増減式の部分にbreakを入れた場合の振る舞いが、gcc9とそれより前のバージョンで異なることで、この問題が発生しているようです。

どちらかというと、gcc9より前では間違った動きをしていたので、gcc9ではそれが修正されているということのようですね。

Qt5ではこれを受けてかforeachのマクロ定義が異なった処理に修正されていますので、gcc9でコンパイルしても問題ないようです。

いずれにせよ、Qt4とgcc9の組み合わせで使用せざるを得ない場合は、foreach文の使用を避けて、通常のfor文や拡張for文を使うか、イテレーターを使ってコンテナに対してのループを回す必要があるということですね。

2
1
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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?