C++標準化委員会の文書 2015-09 pre-Kona: P0011R0-P0020R0
P0011R0: Additions to Filesystem supporting Relative Paths
filesystemライブラリに相対パスを作り出す関数の追加。
以下のように使える。
using namespace std::experimental::filesystem ;
path Path = "/a/d";
path Start = "/a/b/c";
auto RelPath = relative( Path, Start );
assert( RelPath == path("../../d") );
assert( Path == normalize( Start/RelPath ) );
P0012R0: Make exception-specifications be part of the type system, version 4
例外指定を型システムに含める提案。
現在、例外指定は型システムに含まれていない。例外指定された関数へのポインターについて僅かに言及があるだけである。これにより、違法であるべきコードが合法になってしまったり、合法になって欲しいコードが違法になってしまったりする。解決には、例外指定を型システムに含めるしかない。
P0013R0: Logical Operator Type Traits
任意個のtraitsを受け取って論理値を返すand_, or_, not_の追加。それぞれ以下のように宣言される。
template < typename ... B >
struct and_ ;
template < typename ... B >
struct or_ ;
template < typename ... B >
struct not_ ;
以下のように使う。
template < typename T >
void f()
{
constepxr bool b = and_< std::is_copy_constructible<T>, std::is_copy_assignable<T> >::value ;
}
また、これの変数テンプレート版である、and_v, or_v, not_vも提供される。
[PDF注意] P0014R0: Proposal to add the multiline option to std::regex for its ECMAScript engine
std::regexにregex_constants::multilineを追加する提案。^と$とが、文字列全体の先頭と末尾ではなく、各行の先頭と末尾にマッチするようになる。
// マッチ数をカウントする
unsigned int count_match( std::string const & text, std::regex const & re )
{
std::sregex_iterator iter( text.cbegin(), text.cend(), re ) ;
std::sregex_iterator end ;
unsigned int count = 0 ;
for ( ; iter != end ; ++iter )
{ ++count ; }
return count ;
}
int main()
{
std::regex const re1( R"(^[^]*?$)", std::regex_constants::ECMAScript ) ;
std::string text = R"(this is
a
test.)" ;
std::cout << count_match( text, re1 ) ; // 1
// multilineオプション
std::regex const re2( R"(^[^]*?$)", std::regex_constants::ECMAScript | std::regex_constants::multiline ) ;
count_match( text, re2 ) ; // 3
}
P0015R0: A specialization-friendly std::common_type
std::common_typeの実装を変えて、ユーザーが特殊化するときにCV修飾子はリファレンス修飾子の違いによって何種類も明示的特殊化を書かずにすむようにする提案。
P0017R0: Extension to aggregate initialization
アグリゲート初期化を拡張して、基本クラスを持つ型でも初期化できるようにする提案。
C++11のアグリゲート初期化は、基本クラスがある場合には使えない。
struct unique_id { std::uint32_t id ; } ;
struct user : unique_id
{
std::string name ;
} ;
// エラー
user Adams{ "Douglas Adams"} ;
そのため、基本クラスがある場合には、面倒なコンストラクターを書かなければならない。
user( std::uint32_t id, std::string const & name )
: unique_id{id}, name(name)
{ }
このようなボイラープレートコードは書きたくない。そこで、アグリゲート初期化を拡張して、基本クラスもメンバーのように初期化できるようにする。
user Adams { {42}, "Douglas Adams" } ;
複数の基本クラスがある場合は、記述された順番に初期化する。
struct unique_id { std::uint32_t id ; } ;
struct Name { std::string name ; } ;
struct user : unique_id, Name { } ;
user u{ {0}, {"null"} } ;
まあ、便利そうだ。
P0018r00 : Lambda Capture of *this by Value
lambda式で*thisを値でキャプチャできるようにする提案。
struct X
{
int data ;
std::function<int ()> f()
{
return [*] { return data ; }
}
} ;
int main()
{
std::function< int () > f ;
{
X x ;
f = x.f() ;
}// xは破棄された
f() ; // OK、*thisはコピーキャプチャされている
}
キャプチャーデフォルト*は=とほぼ同じだが、thisポインターではなく、*thisを値でコピーキャプチャーする。
*thisだけをコピーキャプチャする、*thisもシンプルキャプチャーとして書ける。
P0019r00 : Atomic View
非アトミック型のオブジェクトに対してアトミック操作をするviewライブラリの提案。
atomic_viewは、非アトミック型の単一のオブジェクトに対してアトミック操作を提供する。
int x = 0 ;
i = 42 ;
{// iへのこれ以前の操作は全て行われる
std::atomic_view<int> ai(i) ;
// atomic<int>風の操作ができる
// aiを介して操作する限りアトミックになる
}// ai破棄、aiへの操作がiに反映される
実装方法として最も汎用的なものは、mutexのような排他的ロックを使うことだ。もっと効率的な方法としては、まずアトミック型にコピーして、アトミック型のオブジェクトを経由して操作を行い、viewオブジェクトが破棄されるときに元のオブジェクトに結果をコピーするというものだ。
atomic_array_viewは、非アトミック型の配列に対するアトミック操作を効率的に行う意図で用意されている。例えば、排他的ロック実装の場合、ロックを要素ごとではなく配列全体に対して単独で用意できる。
想定用途は巨大な配列に対する高パフォーマンス演算だ。以下のような用途を想定している。
- 巨大な非アトミック型の配列を確保する
- 並列の競合しない初期化を非アトミック操作で高速に行う
- atomic_array_viewを構築する
- 並列の競合する書き込みをview経由で行う
- viewを破棄
- 並列の競合しない読み込みを非アトミック操作で高速に行う
atomic_global_viewは、グローバルにアクセス可能なアトミック型のオブジェクトをアトミックに操作するためのviewだ。インターフェースはatomic_viewと同じ。意図としては、アトミック型へのコピーを行わず、元となる非アトミック型を直接操作するものらしい。
P0020r00 : Floating Point Atomic View
非アトミックな浮動小数点数型に対するアトミック操作を提供するatomic_viewに、整数型と同等のメンバーを追加する提案。
add/sub/fetch_add/fetch_sub/operator +=/operator -=が追加される。
ドワンゴ広告
この記事はドワンゴ勤務中に書かれた。
ドワンゴは本物のC++プログラマーを募集しています。
CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0