2011-04-20 「アンジェ、英語が全然ダメ子さんなので……」
FDIS の不満点
C++0x の FDIS について、細かい部分で幾つか不満な点が見つかったので、メモしておきます。
本来なら FDIS を採択した Madrid meeting 以前に言うべきであった事ばかりで、機を逃した感じですが、
気づいておきながら何も主張しないよりはマシだと思ったので。
std::basic_string の swap が noexcept 指定されていない
http://d.hatena.ne.jp/gintenlabo/20110413/1302689739 にも書いたとおり、
move ctor や move 代入演算子は noexcept 指定されているので、 swap も noexcept 指定するべきです。
英訳メモ(後で使うかも):
Functions std::basic_string::swap and std::swap( basic_string&, basic_string& ) should be marked as noexcept, because each of them has a wide contract, and a move ctor and a move assignment operator of std::basic_string are marked as noexcept.
char8_t 欲しい
要は char16_t や char32_t と同じように、他の型と区別される char8_t が欲しいってことですね。
すごく欲しいです。
英訳メモ(後で使うかも):
A type char8_t is required for UTF-8 string literals, which is distinct from char or any other integral types, to avoid encoding problems:
void f( char8_t const* utf8 ); f( u8"あいうえお" ); // OK. The string literal is encoded with UTF-8. f( "あいうえお" ); // should be ill-formed, // because it may be encoded with a encoding other than UTF-8.
一部のメタ関数を SFINAE に使えるようにしたい
現状、 std::result_of や std::common_type といった「型を取得するメタ関数」は、
与えられた型が前提条件を満たさない場合、クラステンプレートの内部でコンパイルエラーとなるため、 SFINAE に使うことが出来ません:
template< class F, class... Args > typename std::result_of<F(Args...)>::type invoke( F && f, Args&&... args ); struct X {}; void invoke( X const& ); int main() { invoke( X() ); // result_of の内部でコンパイルエラーになる }
勿論、これは decltype*1 を使って書き直せばいいのですが、
std::result_of や std::common_type の方が記述量が少なくて済むので、出来ればこっちを使いたいです。
規格を改めるとしたら、
前提条件を満たさない場合は nested type named type は定義されない
的な文章を何処かに追加すればいい感じでしょうか。
その場合は std::common_type の文面も変更する必要がありますね。
暗黙の move の適用範囲が狭すぎる
現行ドラフトでは、関数の戻り値と同じ型を持つローカル変数(および引数)を
return 文でそのまま返す場合、そのローカル変数は暗黙のうちに move されます:
struct Hoge {}; std::shared_ptr<Hoge> f() { std::shared_ptr<Hoge> p( new Hoge() ); return p; }
つまり、上記のコードにおいて、 p は暗黙のうちに move されるので、
例え NRVO をサポートしていないコンパイラであっても、上記のコードにおいて、
参照カウントが無駄にインクリメント&デクリメントされる事はありません。
しかし、この暗黙の move は、暗黙の型変換が絡む場合には行われません。つまり、
struct Base {}; struct Derived : Base {}; std::shared_ptr<Base> f() { std::shared_ptr<Derived> p( new Derived() ); return p; }
上記の関数において、 p が暗黙のうちに move されることはない、ということです。
といっても、 std::shared_ptr 程度なら、 move が copy になっても それほどコストが増えるわけではありません。
問題は、 std::list のような、コピーコストの高いクラスから暗黙変換される場合で、
template< class T > struct wrapper { T value; wrapper( T && x ) : value( std::forward<T>(x) ) {} wrapper( T const& x ) : value( x ) {} }; wrapper<std::list<int>> f() { std::list<int> ls; // 大量に要素を追加 return ls; // 明らかに ls はこれ以上使われないのに、 move されない }
上記のようなコードは、要素数次第では無視できないコストがかかります。
といっても、このような場合ならば、明示的に return std::move(ls); と書けばいい話です。
真に問題になるのは、コピーコストが大きいが、互換性の都合で未だ move に対応していない場合、
あるいは move においてもそれなりのコストがかかるような場合で、
その場合は return std::move(x); と書くと NRVO が発動しないので、明示的に move しないケースよりコストが上乗せになってしまうのです。
この問題に、現行ドラフトの文面を変更しない形で対処するには、
コピーコストが大きくなる場合には、コピー自体を禁止したラッパークラスを作ってしまえばいい、ということが考えられます。
template< class T > struct noncopyable : T { template< class... Args, class = typename std::enable_if<std::is_constructible<T, Args...>::value>::type > explicit noncopyable( Args&&... args ) : T( std::forward<Args>(args)... ) {} noncopyable( noncopyable const& ) = delete; noncopyable( noncopyable && ) = default; noncopyable& operator=( noncopyable const& ) = delete; noncopyable& operator=( noncopyable && ) = default; }; noncopyable<std::list<int>> f() { noncopyable<std::list<int>> ls; // 大量に要素を追加 return ls; // もし暗黙に copy されるような場合にはコンパイルエラーとなる(今回は問題なし) }
一方で、このようなラッパーには限界も存在します。
std::list<int> f() // 戻り値を noncopyable 以外にすると { noncopyable<std::list<int>> ls; // 大量に要素を追加 return ls; // 暗黙にコピーされる、エラーにもならない }
なので、可能なら規格を改めて、
関数の return 文が return name ; という形で、 name が参照以外のローカル変数または引数の場合には、
一律で暗黙の move が働くようにした方が良いのではないか、と思った次第。
* * *
と、このような些細な不満点はあるものの、
じゃあ再び FDIS を採択しよう、となると、8月の Bloomington meeting まで待たなければいけないので、
現実で妥協するのも仕方ない気がします。 今となっては、一刻も早く制定される方が良いなぁ、と。
ともあれ、ユーザ定義リテラルは滅ぶべきであると考える次第である。
- 790 http://pipes.yahoo.com/pipes/pipe.info?_id=42a62e001a92fb50f5884f571330f822
- 35 http://twitter.com/
- 25 http://d.hatena.ne.jp/seikenn/20100203/programmingMaster
- 20 http://cpp.ring.hatena.ne.jp/
- 19 http://www.google.co.jp/url?sa=t&source=web&cd=1&ved=0CBkQFjAA&url=http://d.hatena.ne.jp/gintenlabo/20110223&rct=j&q=std::decay&ei=9t2vTY-wLo-avgPf3P2HBw&usg=AFQjCNEYISdI0AdNEsWL68N5HAr32V0vdw&sig2=awwADCZb9WjMYXUR_6hJmQ
- 16 http://d.hatena.ne.jp/
- 12 http://reader.livedoor.com/reader/
- 12 http://www.google.co.jp/
- 10 http://www.google.co.jp/search?sourceid=navclient&hl=ja&ie=UTF-8&rlz=1T4GGHP_jaJP425JP425&q=安全なMOVE
- 9 http://d.hatena.ne.jp/iorate/
