Tambourine作業メモ

主にスキル習得のためにやった作業のメモ。他人には基本的に無用のものです。

C++でも遊んでみたい

2019年にもなって、C++を勉強しなくてはいけなくなった。嘆かわしい。

C++は大変に歴史があり、かつ、あり得ないぐらいに幅広く使われているので、大量の歴史的経緯を抱えている。 そのため、実体がよくわからない。私が最後にC++を勉強したのは20世紀のことなので、2019年モデルへの アップデートが必要である。まあ、ぶっちゃけ何にもおぼえてないので、位置から勉強する。

まずは教科書選びが必要。どれが良いのかはさっぱりわからないが、ここはC++の作者であるStroustrupさん自らが書いた、わりと新しめの教科書があるので、それを使ってみよう。もう一冊、いわゆるバイブル(言語作者自らが書いた本)があるようだけど、1万円ぐらいするのでこっちにしとく。

C++によるプログラミングの原則と実践

C++によるプログラミングの原則と実践

この本は、C++の本というよりもC++でプログラミングを学ぶ本だ。これはこれでStroustrupさんの思想信条が伝わってくる気がするのでいいと思っているけども、流石に大学1年生ではないので、すごい勢いで飛ばし読みすることになる。なんせ1200ページもあるのだ。基本、ざっと読んで、練習問題をやっていく感じになる。

まずは、第2章のドリルから。お約束のHello, Worldである。最大の難関だ。

以下のコードを、ビルドして実行せねばならない。

#include "std_lib_facilities.h"

int main()
{
    cout << "Hello, World\n";
    keep_window_open();
    return 0;
}

付録に環境構築の方法があるからそこを見て頑張れと書いてあるが、 そこに書いてあるのはVisual Studio のExpress版のインストール方法である。おまいがー。

とはいえ、Windowsと違って私のMacGCCが入っていなければロクに動くはずもない。 コマンドを打てばどうにかなるはずだ。打たずにどうにかしたいのだ。ぶっちゃけcargo runしたいのだ。ワガママだ。

とりあえず、Visual Studio Codeを立ち上げて、さっきのコードをhello.cppとして保存したところ 「ちょ、おまっ。お前、C++書いたな?書いたんだな?じゃあ、このプラグイン入れるか?入れるよな?」(超訳)と VS Codeが仰いますので、おとなしくプラグインを入れる。 入れて立ち上げ直して、メニューの[Run Build Task...]を選ぶと、clangを使うかg++をつかうかリストで選ばされる。 特に理由もなくg++を選ぶ。もちろんエラーである。

> Executing task: /usr/bin/g++ -g /Users/tambara/study/cpp_study/hello.cpp -o /Users/tambara/study/cpp_study/hello <

/Users/tambara/study/cpp_study/hello.cpp:1:10: fatal error: 'std_lib_facilities.h' file not found
#include "std_lib_facilities.h"
         ^~~~~~~~~~~~~~~~~~~~~~
1 error generated.
The terminal process terminated with exit code: 1

Terminal will be reused by tasks, press any key to close it.

とりあえず、コマンドを打たなくてもg++コマンドを実行してくれたことが驚きだ。世の中は進歩している。 しかしながら、エラーだ。「std_lib_facilities.hってなんすか?」と聞かれている。

うん、私も同感だ。

どうやらこれは学習用にStroustrup先生が用意してくれたヘッダファイルのようだ。 ダウンロードして使えばいいらしい。これを使わないのならば、代わりに

#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
inline void keep_window_open() { char ch; cin >> ch; }

と書けとしてある。なるほど、教育的である。ちなみに最後のkeep_window_open()は何かというと、 WindowsでVSからビルドして実行したときにコマンドプロンプトの画面が一瞬で閉じてしまうと なにが起きたかわからないので用意された関数である。教育的すぎて凄い。

先生のサイトからダウンロードし、cppファイルと同じディレクトリにおいてみる。

再度、ビルドしてみよう。

> Executing task: /usr/bin/g++ -g /Users/tambara/study/cpp_study/hello.cpp -o /Users/tambara/study/cpp_study/hello <

In file included from /Users/tambara/study/cpp_study/hello.cpp:1:
In file included from /Users/tambara/study/cpp_study/std_lib_facilities.h:34:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/ext/hash_map:213:5: warning: Use of the header
      <ext/hash_map> is deprecated. Migrate to <unordered_map> [-W#warnings]
#   warning Use of the header <ext/hash_map> is deprecated.  Migrate to <unordered_map>
    ^
In file included from /Users/tambara/study/cpp_study/hello.cpp:1:
/Users/tambara/study/cpp_study/std_lib_facilities.h:43:20: error: no matching function for call to object of type 'hash<char *>'
            return hash<char*>()(s.c_str());
                   ^~~~~~~~~~~~~
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/ext/__hash:38:12: note: candidate function not
      viable: 1st argument ('const std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::value_type *'
      (aka 'const char *')) would lose const qualifier
    size_t operator()(char *__c) const _NOEXCEPT
           ^
1 warning and 1 error generated.
The terminal process terminated with exit code: 1

Terminal will be reused by tasks, press any key to close it.

warningはdeprecateだよと言われているだけなのでいいかな。

エラーの方はさっぱりわからないが、ググったらまったく同じようにこの本を使って勉強している人がStack Overflowに書き込みをしている。

stackoverflow.com

なるほど、わからん。

でも、constを付ければ良いようだ。その通りに修正してみる。

> Executing task: /usr/bin/g++ -g /Users/tambara/study/cpp_study/hello.cpp -o /Users/tambara/study/cpp_study/hello <

In file included from /Users/tambara/study/cpp_study/hello.cpp:1:
In file included from /Users/tambara/study/cpp_study/std_lib_facilities.h:34:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/ext/hash_map:213:5: warning: Use of the header
      <ext/hash_map> is deprecated. Migrate to <unordered_map> [-W#warnings]
#   warning Use of the header <ext/hash_map> is deprecated.  Migrate to <unordered_map>
    ^
1 warning generated.

Terminal will be reused by tasks, press any key to close it.

おー、ちゃんと実行ファイルができた。

> ./hello
Hello, World
Please enter a character to exit

a