2013-04-23

Bristol会議でC++14ドラフト入りが決まった提案一覧

C++14が来年に迫っている。先日行われたBristol会議の投票により、C++14のドラフトに正式に入ることが決まった提案の一覧を紹介する。ここで紹介されている提案は、すべてC++14入りが決定している。この先も細かい変更があるかもしれないが、基本的には変わらない。来年2014年に正式に発行される予定のC++14におそらく入る。

また、論文はすでに公開されている論文を、議論の結果修正したものなので、すでにこのブログでは全て解説しているはずだ。以下から探してくれたまえ。

本の虫: C++WG 2013-03-pre-Bristol mailingの簡易レビュー
本の虫: C++ 2013-01 mailingの簡易レビュー
本の虫: 2012-11 post-Portland mailingの簡易レビュー
本の虫: 2012-09 pre-Portland mailingのあまり簡易ではないレビュー
本の虫: 2012-02 post-Kona mailingの簡易レビュー
本の虫: 2011-01 pre-Kona 2012 mailingの簡易レビュー

参照している論文は、Post-Bristol mailingで公開される予定だ。最近C++WGの方針が変わり、このインターネット時代では、すでに書き終えた論文は一刻も早く公開すべきであるということになり、C++財団のWebサイトで公開されている。

[吐き気を催すPDF] N3651: Variable Templates (Revision 1)

変数の宣言もテンプレート宣言できるようにする提案。

今のC++では、型をパラメータ化した定数の宣言が難しい。これは、変数をテンプレート化できないためである。

constexpr double pi = 3.14 ;

この例では、piの型はdoubleである。したがって、piを使う文脈では、どこでもdouble型が使われてしまう。ではもし、floatとかintとかmy_floating_pointとかの型に対する円周率の定数を定義したければどうすればいいのだろうか。

クラステンプレートのメンバーを使うとか、constexpr関数テンプレートを使うとかいう手もある。

// 関数テンプレート
template < typename T >
constexpr T pi()
{
    return static_cast<T>(3.1415926535897932385) ;
}

// 明示的特殊化
template < >
constexpr my_floating_point pi< my_floating_point > ()
{
    return /* ユーザー定義クラスを返す実装 */ ;
}

関数テンプレートを定数として使う問題は、定数の利用には、関数呼び出しの文法が必要になることだ。

// 円の面積を求める
template<typename T>
T area_of_circle_with_radius(T r)
{
    return pi<T>() * r * r;
}

この()は冗長である。「定数とは無引数関数で表現できるんだ」などと主張したとしても、数学者ではないプログラマーには受け入れられない。この問題は、変数宣言にテンプレート宣言が許されていれば解決できる。

// 変数テンプレート
template < typename T >
constexpr T pi = static_cast<T>(3.1415926535897932385) ;

// 明示的特殊化
template < >
constexpr my_floating_point pi<my_floating_point> = /* 初期化 */

// 円の面積を求める
template<typename T>
T area_of_circle_with_radius(T r)
{
    // 変数テンプレートを実体化して使用
    return pi<T> * r * r;
}

とても斬新な機能だが、文面の変更としては極めて小さい。というのも、従来の変数宣言にはテンプレート宣言を使えなかった制限をとりはらうだけだからだ。

前回からの変更点は、constexprやconstではない変数テンプレートも許可すること。

// OK
template < typename T >
T x = 0 ; 

変数テンプレートのテンプレートテンプレートパラメーターは、熟考が必要だということで、C++14では禁止されることだ。

N3649: Wording for Auto Generic Lambda Proposal (Bristol 2013)

ジェネリックlambda。lambda式の仮引数の型をパラメーター化できる。

void f()
{
    auto l = []( auto x ) { } ;

    l( 0 ) ;
    l( 0.0 ) ;
    l( "hello" ) ;
}

もちろん、キャプチャーしないlambda式は、関数ポインターに変換可能だ。

void f()
{
    auto l = []( auto x ) { } ;

    auto (*p1)(int) -> void = l ;
    auto (*p2)(double) -> void = l ;
}

クラスで定義した関数オブジェクトならば、メンバーテンプレートを使うことで実現できていたジェネリックが、lambda式でも可能になる。

今回の論文は、前回からだいぶ変更点されている。

一番大きいのは、Variadic auto parametorsだろう。

void f()
{
    auto l = []( auto ... pack ) { }

    l( ) ;
    l( 1 ) ;
    l( 1, 2 ) ;
    l( 1, 2, 3, 4, 5 ) ;
}

C++14では、lambda式がますます使いやすくなるだろう。

N3668: exchange() utility function, revision 3

アトミック版ではない汎用的なexchange関数テンプレートの追加。実装は以下の通り。

template<typename T, typename U=T>
T exchange(T& obj, U&& new_val)
{
    T old_val = std::move(obj);
    obj = std::forward<U>(new_val);
    return old_val;
}

N3656: make_unique (Revision 1)

型のオブジェクトをnewしてunique_ptrにいれて返すmake_unique関数テンプレートの追加。make_sharedのunique_ptr版だ。これにより、new式を書かずにすむ。

#include <memory>

int main()
{
    std::unique_ptr< int > p1 = std::make_unique< int >( ) ;
    std::unique_ptr< int > p2 = std::make_unique< int >( 123 ) ;

    // int[10]
    std::unique_ptr < int [ ] > p3 = std::make_unique< int [ ] >( 10 ) ;
}

これは何をしているのか分かりやすくするために型を書いているが、現実にはautoを使うところだ。

#include <memory>

int main()
{
    auto p1 = std::make_unique< int >( ) ;
    auto p2 = std::make_unique< int >( 123 ) ;

    // int[10]
    auto p3 = std::make_unique< int [ ] >( 10 ) ;
}

重要なのは*p1で値を得られることであり、型ではないからだ。

あって当然の機能だ。これがない現行のC++11の標準ライブラリはクソである。

N3654: "quoted" proposal

空白付きの文字列をそのままストリームに出力し、また入力するマニピュレーター。

正直、ストリームライブラリは教科書のサンプル以上のことをしようとすると、とたんに厄介になるので、何も期待していない。

[無慈悲なPDF] N3642: User-defined Literals for Standard Library Types

標準ライブラリ用のユーザー定義リテラル。標準ライブラリの特権を行使して、アンダースコアからは始まらないリテラル識別子を使っている。うらやましい限りだ。

[C++WG論文をHTMLで記述すべき勧告が論文で出された] N3655: TransformationTraits Redux, v2

従来の標準ライブラリ内のメタ関数に対するエイリアステンプレートを提供する提案。metafunction<T>::typeが、metafunction_t<T>になる。ようするにこういうことだ。

template < typename T >
using add_pointer_t = add_pointer<T>::type ;

冗長な文法で書かなくてよくなる。

N3672: A proposal to add a utility class to represent optional objects (Revision 4)

標準ライブラリにoptionalを追加する。もはや有名すぎて解説するまでもあるまい。今時optionalを知らないのは、いまだにMSVCを使っているようなアホだけだ。

N3659: Shared Locking Revision 2

標準ライブラリにReader/Writer locksライブラリのShared lockingライブラリを追加する。

読む分にはいくらでも読んでいいが、書き込む際には排他的にロックしたいという場合に便利な同期ライブラリだ。

No comments: