今回は、C++03からC++11にかけて変わった互換性の問題を引き起こすおそれのある、今やおなじみになったシリーズの、アルゴリズム編だ。
変更:一部のアルゴリズムの、入力の結果の挙動が、ある未規定な状態から、別の未規定の状態に変わる。
これは、C++11にムーブが導入されたためだ。std::removeやstd::remove_ifなどが該当する。
// C++03とC++11で挙動が変わる例
#include <vector>
#include <algorithm>
template < typename T >
void f( T const & t1, T const & t2, T const & t3 )
{
// t1, t2, t3はそれぞれ等しくないオブジェクトであるとする
std::vector<> v ;
v.push_back( t1 ) ;
v.push_back( t2 ) ;
v.push_back( t3 ) ;
// vectorの要素 { t1, t2, t3 }
std::remove( v.begin(), v.end(), t2 ) ;
// vectorの要素 { t1, t3, 未規定の状態 }
}
C++03でも、C++11でも、このコードを実行した後のv[2]の状態は、未規定である。ただし、C++03では、コピーされるのに対し、C++11では、ムーブされる。そのために、未規定は未規定でも、異なる状態の未規定になる。
これは、元々が未規定の状態になるという点においては変わらないので、それほど問題になることはないだろう。C++11規格では、標準ライブラリに渡すユーザー定義型のムーブ後の状態は、未規定だが、規格の型に対する要求(たとえば、DefaultConstructibleを満たすとか)は、依然として満たしていなければならないと規定している。これはユーザーの責任でもある。
次回は数値ライブラリについて。
最後の行のコメントですが、v[1] の内容は t2 ではなく t3 ではないでしょうか?
ReplyDelete