Edited at

C++11をC++03に戻さなきゃいけなくて辛い話(書きかけ)

More than 3 years have passed since last update.

C++11使えないC++とかもはやC++使う意味がないこの世の中ですが、どうしてもC++11に対応してない酷コンパイラ様(某ふじなんとか社製)のためにC++03に戻すお仕事をしています。

あまりにも色々つらいので、つらかったことをまとめておいたら、少しでも似たような境遇の人の救いになるかなと思ってまとめてみます。

まだ作業中ですので、増えたら増えた時に書いてきます。


autoがない

ひとつずつやっていけば直せるけど地味にメンドイですね。

特にイテレータまわりが大変です。std::map< std::string, std::vector< std::pair<int, double> > >::iteratorとかなんなんでしょう・・・。


ラムダ式がない

なんといってもコレが一番きつかった。

C++11でこんなコードがあるとします

#include<iostream>

#include<vector>
#include<numeric>
#include<cmath>

int main()
{
constexpr double offset = 1.5;

const std::vector<double> values = {1.1, 1.2, 1.3, 1.4, 1.5};

// こんな感じでstd::accumulateなどで外の変数(クロージャ)を使いたい
const double result = std::accumulate(values.cbegin(), values.cend(), 0.0,
[&offset](const double sum, const double val)
{
return sum + std::sin(offset + val);
});

std::cout << result << std::endl;

return 0;
}

C++03では当然ラムダ式が使えません。

となるとファンクタの出番です。

(クロージャのないラムダ式なら関数ポインタでもなんとかなりますが)

試行錯誤した結果C++03ではこんな風になりました

#include<iostream>

#include<vector>
#include<numeric>
#include<cmath>

// クロージャありのラムダ式をファンクタにする場合こんな風にするしかない
// (しかもC++03では関数スコープ内のローカル型はテンプレート引数に使えないから、外に出さなきゃいけない)
struct Lambda
{
// メンバー変数でコピー走らせたくないから参照にする
const double& offset;

// 参照を持つメンバー変数はコンストラクタが必要(引数を参照にするのを忘れないこと!)
Lambda(const double& offset) : offset(offset) {}

double operator()(const double sum, const double val)
{
return sum + std::sin(offset + val);
}
};

int main()
{
const double offset = 1.5;

std::vector<double> values;
values.push_back(1.1);
values.push_back(1.2);
values.push_back(1.3);
values.push_back(1.4);
values.push_back(1.5);

const double result = std::accumulate(values.cbegin(), values.cend(), 0.0, Lambda(offset));

std::cout << result << std::endl;

return 0;
}

つらいですね。