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

MinGWでto_stringにハマった話

僕は普段競技プログラミングをしてるのでC++を使っているのですが、その際にto_stringという便利そうな関数を見つけて闇に落ちたという話です。
 競プロをしていると、しばしば文字列を数値に変換したり数値を文字列に変換したくなることがあります。僕はC++の関数をあまり信じていない*1(というより、使い方を間違えてバグらせるのが怖い)ので以下のコードのように基本的に自分でループを回して数値を文字列にしたり文字列を数値にしていました。

//文字列を数値に
string str;
int num = 0;
for(int i = 0; i < str.size(); i++){
    num = num*10+str[i]-'0';
}
//数値を文字列に
int num;
string str;
while(num){
    char x = '0'+num%10;
    str.push_back(x);
    num /= 10;
}
reverse(str.begin(),str.end());

 数値を文字列に変換する関数として、stringstreamやsprintfは使ったことがありましたが、stringstreamは数値を文字列に変換するには大袈裟すぎてタイプ量が多くなるし、sprintfはバッファとかめんどくさいのでそれなら上のように自分で書けばいいじゃんと思ってました。
 しかし、もしかしたらc++11やc++14には便利な関数ができたんじゃないか*2と思って調べてみたら見つかったのがこのto_stringでした。

int num;
string str = to_string(num);

これだけで済むらしいということを知り、テンションが上がって、早速先ほどのto_stringを使ったコードを実行しました。しかし、to_stringなんて関数は宣言されてないよと怒られます。bits/stdc++.hをインクルードしてるのでおかしいなと思い、とりあえずググってみるとstackoverflowにおいて、それはg++のバグだよなどという恐ろしいことが書いてありました。

パッチ*3もおいてあったのですが、とりあえずg++を最新版にしたら直るという情報があったので、mingwを最新版にして、もう一度実行してみました。しかし、やはりto_stringなんてないと言われます。

仕方ないので先ほどのパッチを当てましたが、すると今度はbits/stdc++.hのせいといえばそうなのですが、ctime.hとwchar.hにtmという構造体が存在しており、衝突してしまいました。しかも、パッチを当てるときにバックアップとらずに上書きしてしまったので(アホ)任意のコードについてコンパイルエラーを吐くようになってしまいました。
 再インストールすれば直るという話もあったし、そもそもコンパイルが通らなくなったのでc:\Mingwを削除して*4、削除されたことを確認するためにg++ -vをしてみると、

ん??
僕は情弱なのでここから多くは読み取れませんが、とりあえずhaskellのプラットフォームの中にmingwが入っていたらしく、c:\直下のMinGWが消えたためこれが選ばれるようになったようです(確かにhaskellを使うためにpathは通していた)。なんか、僕のPCゴチャゴチャすぎてやばいなぁと思いつつも一応先ほどのto_stringを入れたプログラムを投げてみる。コンパイルできた。動いた。終わり。え???
 というわけで、無事に解決しました(完)。

*1:upper_boundやlower_boundも毎回自分で実装しているのは流石に頭悪いと毎回思っています

*2:僕が使っているc++11の機能はメルセンヌツイスタの乱数とunordered_mapぐらいです

*3:Enabling string conversion functions in MinGW

*4:調べてみたらアンインストールは必要ないっぽかったので(?)