2016-03-16

C++標準化委員会の文書: P0119R1-P0138R1

今回から、個人的な感想も意図的に書いてみることにした。

[PDF] P0119R1: Overload sets as function arguments

オーバーロードされた関数の名前からlambda式を暗黙に生成する機能の提案。

オーバーロードされた関数名は、関数の集合を表すので、テンプレート実引数に渡すことはできない。

void f( int ) ;
void f( double ) ;

template < typename Func >
void g( Func func ) ;

int main()
{
    // エラー
    // どのfか曖昧
    g( f ) ;
}

これは、lambda式を経由すれば渡すことができる。

g( []( auto && x ) -> decltype(auto) { return f( x ) ; } ) ;

しかし、こんな自明なlambda式をわざわざ書くのは面倒だ。そこで、関数のオーバーロードのセットを指すid-expressionが実引数として指定されたら、このようなlambda式を生成するテンプレートの実引数推定を追加する提案。

テンプレートの実引数推定にルールを追加するので、autoで受けることもできる。

auto less = (<) ;
less( a, b ) ;

確かに便利だが、どの程度の需要があるだろうか。

[PDF] span: bounds-safe views of objects for sequences

連続したストレージとそのサイズを管理して配列のようにアクセスできるライブラリspanの提案。

もともとは、多次元配列としても使えるarray_viewの提案だったが、多次元配列サポートをなくし、また名前も変えてspanとした。Guidelines Support Libraryのspanを

spanは、連続したストレージとその長さを管理できる。つまり、ポインターとその長さを管理するためのクラスだ。

最近のC++の標準ライブラリには、このような"vocabulary type"の提案が多い。vocabulary typeはコードを読みやすくする。

spanはコンパイル時の配列の長さ指定と、実行時の配列の長さ指定の両方をサポートする。

int a[10] ;
// コンパイル時に長さを指定した固定長span
span<int, 10> s1{ a } ; 
// 実行時に長さを指定した動的長さspan
span<int> s2{ a, 10 } ;

spanを経由した配列へのアクセスには範囲チェックが行われる、範囲外アクセスは未定義の動作を引き起こす。固定長と動的長さspanは相互に代入可能だが、長さのチェックはもちろん行われる。

実際の使い方は、arrayとほぼ同じだ。

興味深いのは、P0257の提案されているbyteを使って、standard layout型Tのspan<T>をspan<byte>に変換することで、内部表現を読み書きすることをサポートしている点だ。キャストを手で書かずに済む。

このライブラリは便利なのでほしい。

[PDF] P0123R1: string_span: bounds-safe views for sequences of characters

string_viewがstring_spanに改名された。文字列を共通の方法で操作できるラッパーライブラリ。

string_viewの方がわかりやすい気がするが自転車小屋について議論しても仕方がないのだろうか。

P0124R1: Linux-Kernel Memory Model

Linuxカーネルのメモリモデルについて不文律であるところも含めて完全に解説する文書。

背景として、Linusにatomic操作ライブラリは使い物にならんと言われたので、まずLinuxカーネルにおけるメモリモデルを理解するところから始めるそうだ。

[PDF] P0126R1: std::synchronic<T>

リソースを浪費せずに、あるオブジェクトの値が期待する値になるまで待つライブラリ、std::synchronic<T>の提案

使い方は極めて原始的なcondition variableに近い。

P0128R1: constexpr if

コンパイル時条件分岐constexpr ifの提案。

前回からの変更点は、一つの新しいキーワードconstexpr_ifから、既存のキーワードを連続したconstexpr ifになったこと。

template < typename T, typename ... Rest >
void f(T && t, Rest && ... rest )
{
    constexpr if ( sizeof...(rest) )
    {
        // tを処理
        // 引数ゼロ個のfのオーバーロードは必要ない。
        f( std::forward<Rest>(rest)... ) ;
    }
}

constexpr elseもある。

constexpr if ( ... )
{

}
constexpr else
{

}

どういう形であれ、コンパイル時条件分岐はほしい。

[PDF] P0138R1: Construction Rules for enum class Values

enumを強いtypedefの代わりに使える機能の提案。

内部型が指定されていて、enumeratorの存在しないenumは、縮小変換のないリスト初期化を使えば、キャストを使わずに初期化できるようにする提案。

enum class E : int { } ;

E e{123} ;

void f( E e ) ;

void g()
{
    f( { 123 } ) ;
}

キャストが必要なくなるのは初期化だけなので、これでは使い方が煩わしいことに変わりはない。本物の強いtypedefの方がいい。

ドワンゴ広告

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

1 comment:

Anonymous said...

array_viewの多次元サポートがなくなったのはちょっと残念です。画像ライブラリとかに使えそうだったので微妙に期待してました。あんまり多次元過ぎても用途がないのは確かですがね。
C++で例えばWINDOWSとかのコードが書けるようになるとかなりいいのですが、現状結局環境依存です。もっと深層に切り込む仕様にする必要がありますね。