はじめに
VScode上で<bits/stdc++.h>*1に赤線が引かれたり、「識別子 "cout" が定義されていません」だとか「名前空間 "std" にメンバー "cout" がありません」などと言われたりするものの、しかしコンパイルは通るという謎現象に長い間悩まされておりました。それがやっとこさ解決したので、備忘録として置いておきます。
(gcc を使っている人を対象に書いています。clang や VisualStudio 等(最初から<bits/stdc++.h>が入っているわけではない)を使っている人向けの記事ではありません。)
- はじめに
- 1. インクルードパスを確認する
- 2. stdc++.h を探す
- 3. VScode の C/C++ 拡張の設定に追記する
- これで解決…と思いきや
- 4. stdc++.h を開き、いくつかの行をコメントアウトする(しなくてもよかった) 再びC/C++ 拡張の設定に追記する
- まとめ
1. インクルードパスを確認する
ターミナル(Powershell 等)にて、以下のコマンドを実行する
gcc -x c++ -v -E /dev/null
するとだいたいこんな感じに出力される
Using built-in specs. COLLECT_GCC=C:\msys64\mingw64\bin\gcc.exe (中略) #include "..." search starts here: #include <...> search starts here: C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../include/c++/13.1.0 C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../include/c++/13.1.0/x86_64-w64-mingw32 C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../include/c++/13.1.0/backward C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/include C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../include C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/include-fixed End of search list. (後略)
2. stdc++.h を探す
1.で出力されたパスの中から、「『bits』という名前のフォルダが存在し、さらにその中にstdc++.h
というファイルが存在するもの」を探す
- がんばってさがしましょう。
- 自分の場合は
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.1.0/../../../../include/c++/13.1.0/x86_64-w64-mingw32
にありました。
3. VScode の C/C++ 拡張の設定に追記する
拡張機能の一覧から「C/C++」を探し、歯車のマークをクリックして「拡張機能の設定」を開く
設定項目の中から「Default.IncludePath」を探し、「項目の追加」をクリックして2.で見つけたパスを書き込む
- 設定項目の上部にある検索欄に「path」と入力すると探しやすいです。
これで解決…と思いきや
ここまでの設定がうまくいっていれば、<bits/stdc++.h>の赤線は消えているはずです。
ただ、ここでまた別のエラーが発生します。「識別子 "cout" が定義されていません」です。
さすがにusing namespace std
はマズいよな、と思ってstd::
を付け足してみたところで何も解決しません。
ところが#include <iostream>
を付け足すとこのエラーは消えます。
…おかしいですね?#include <bits/stdc++.h> すればiostreamも読み込まれるはずでは?実際コンパイルは普通に通っていますし…。
とりあえず、さっき探したstdc++.h
を開いてみましょう。
4. stdc++.h を開き、いくつかの行をコメントアウトする(しなくてもよかった) 再びC/C++ 拡張の設定に追記する
- だいたい150行目くらいのところに
#include <iostream>
がありますが…なんか暗く表示されてますね? - その上の行を見ていくと…
#if _GLIBCXX_HOSTED
という行がありますね。どうやらこれが原因のようです。 しかし、自分が調べた範囲では、これの定義に関する情報は全く出てきませんでした…。- 定義されているファイルを見つけました。
stdc++.h
が存在するファイルにあるc++config.h
です。この中の1720行目に#define _GLIBCXX_HOSTED __STDC_HOSTED__
という部分があります。 __STDC_HOSTED__
というのは、「ホスト処理系かどうか」を判定する定数で…まともな実行環境ならだいたい1になります。- ではどうすれば認識されるようになるのか…についてはこの後説明します。
- 定義されているファイルを見つけました。
どうせコンパイルは通るわけですし、コメントアウトしちゃいましょう。
100行目あたりの#if _GLIBCXX_HOSTED
および最後の行にある#endif // HOSTED
をコメントアウトする
- ちなみに、他にも暗くなっている行があると思います。
#if __cplusplus >= hogehoge
で始まっているところですね。 - これはC++のバージョンによって決まる定数です。
- 次のコードを参考にして、__cplusplusの値を調べてみましょう。自分の環境では
201703L
でした。 - ところが、VScode上では
199711L
として扱われてしまうようです…。 これもコメントアウトしちゃいましょうと、当初は思っていたのですが、いろいろ調べた結果、C/C++拡張の設定の「Default.Compiler Args」に/Zc:__cplusplus
を追加すれば正常に判定されることがわかりました。やったね。- なんかここまで作業してたらいつの間にか
#if _GLIBCXX_HOSTED
のコメントアウトを外しても#include <iostream>
とかが暗くならないようになってました。ええ…(困惑) settings.json
のC_Cpp.default.compilerPath
の行をコメントアウトしたら元に戻ったので、おそらくこれが問題を解決する鍵なのでしょう。- というわけで正しい手順は以下の通りです。
- 自分の場合は
C:/msys64/mingw64/bin/gcc.exe
でした。
C/C++拡張の設定の「Default.Compiler Path」を探して「settings.jsonで編集」をクリックし、コンパイラのパスを書き込む
まとめ
なんかごちゃごちゃしてきたのでもう一度手順をまとめておきます。
- インクルードパスを確認する
stdc++.h
を探す- VScode の C/C++ 拡張の設定のうち、以下の部分に追記する
- 「Default.IncludePath」に、2.で見つけたパスを書き込む
- 「Default.Compiler Path」に、コンパイラのパスを書き込む
- 「Default.Compiler Args」に、
/Zc:__cplusplus
を書き込む(必須ではない)
以上です。この記事が誰かの役に立つと良いのですが…。
*1:使うべきかどうかについてはここでは議論しません。