C++標準化委員会の文書: P0310R--P0319R0
[PDF] P0310R0: Splitting node and array allocation in allocators
ノードメモリ確保を追加する提案。
listやmapといったリンクリストのデータ構造は、挿入コストがO(1)なのにもかかわらず、最近は敬遠されている。代わりに、挿入コストがO(N)であるunordered_mapが使われている。その理由は、メモリ断片化だ。
メモリ断片化を防ぐために、メモリを一括で確保して切り分けて返したり、解放されたメモリをリンクリストでpoolしておく、ノード専用のメモリ確保方法を、std::allocator_traitsに追加する提案。ノード専用のメモリ確保は、汎用的なpool allocatorよりも速いとしている。
Boost.Containerには同じ発想の実装があるが、C++03時代のstd::allocatorを使っていて、設計が古い。
P0311R0: A Unified Vision for Manipulating Tuple-like Objects
最近、tuple風オブジェクトとunpackingに関しての提案が多いので、そのまとめ。
tuple風オブジェクトとはtupleやpairやarrayのようなクラスや、あるいはアグリゲートのことだ。unpackingとは、構造化初期化のようなtuple風オブジェクトの要素を取り出す操作のことだ。
これ自体は特に新機能の提案をしていないが、tuple風オブジェクトに対するslicing操作が提供されるべきだとしている。例えば、先頭からN個だけunpackingするとか、先頭からN個目から残りをunpackingするとかだ。
[PDF] P0312R0: Make Pointers to Members Callable
メンバーへのポインターを関数呼び出しできるようにする提案。
メンバーへのポインターがメンバー関数を参照している場合、呼び出すのは面倒だ。
struct X
{
void f() { }
} ;
int main()
{
auto ptr = &X::f ;
X x ;
(x.*ptr)() ;
}
メンバーへのポインターは、クラスのオブジェクトを渡してやらなければならない。
現在、INVOKE(C++17ではstd::invokeとしてINVOKE要件を満たす呼び出し方をするテンプレート追加されている)で呼び出し可能なものは4つ。関数、関数ポインター、関数オブジェクト、メンバーへのポインターだ。
int arg ;
void func( int ) ;
auto func_ptr = &func ;
struct func_class
{
void operator () ( int ) { }
} ;
func_class func_obj ;
auto memptr = &func_class::operator() ;
func(arg) ; // 関数
func_ptr(arg) ; // 関数ポインター
func_obj(arg) ; // 関数オブジェクト
(func_obj.*memptr)(arg) ; // メンバーへのポインター
メンバーへのポインターだけ文法が違う。
従来、この文法の差異はライブラリで吸収していた。この提案では、普通に呼び出すことができるようにする。第一引数をクラスオブジェクトとみなす。
// (func_obj.*memptr)( arg )と同等
memptr( func_obj, arg ) ;
これはほしい。
P0313R0: Comparison operators in fold-expressions
fold式から比較演算子を消す提案。C++では、a < b < cのような式は慣習的な数学記法として期待される挙動をしない。そのため、fold式で比較演算子が使えても、メタプログラミングやDSL実装の役に立つだけだ。混乱を考えれば、消すほうが望ましい。
P0314R0: Querying the alignment of an object
alignofを式にも適用できるようにする変更。従来、alignofは型にしか適用できなかった。
int x = 0 ;
alignof(int) ; // OK
alignof(x) ; // エラー
この提案では、式にも適用できる。
int x = 0 ;
alignas (16) int y = 0 ;
alignof(x) ; // alignof(int)
alignof(y) ; // 16
[PDF] P0315R0: Lambdas in unevaluated context
Lambda式を未評価式の中でも使えるようにする提案。
従来、lambdaのoperator()はconstexprではなかったし、未評価式の中では使えなかった。その理由は、テンプレートに渡してSFINAEの文脈で考慮させることを禁止するためである。
もしlambdaがconstexprで未評価式の中で使えるとどうなるか。以下のようなコードが書けるようになる。
template < typename T, bool = []{
T x ;
T y = x ;
auto iter = x.begin() ;
auto end = x.end() ;
iter != end ;
*iter ;
return true ;
}
>
void f()
{
}
これがSFINAEで考慮されるので、lambda式がconceptのように使えるようになってしまう。例えば、上のコードは、T型にデフォルトコンストラクターとコピーコンストラクターとデストラクターとbegin/endメンバー関数があるかどうか。begin/endの戻り値の型はコピーコンストラクターとデストラクター、operator !=とoperator *をサポートしているかどうかによって、SFINAEのルールによってテンプレートのsubstitutionを抑制できる。
問題は、そのような挙動をサポートするには、シグネチャにlambda式全体を含めなければならない。しかし、未評価式での使用を禁止しただけでは、迂回方法がまだある。そこで、エンティティのシグネチャに影響する使い方を直接禁止する文面が入った。
CWG_DEFECTS: C++ Standard Core Language Defect Reports and Accepted Issues
これにより、lambda式を未評価式で使うことを禁止する理由がなくなった。それゆえ、この提案では制限の緩和を提案している。
目的は、tupleなどの型シークエンスへの適用だ。
using sorted = decltype(sort(tuple, [](auto const& a, auto const& b) {
return std::integral_constant<bool, sizeof(a) < sizeof(b)>{};
}));
懸念していた問題が直接解決されたので、無用の制限は緩和すべきだ。
P0317R0: Directory Entry Caching
filesystemにディレクトリキャッシングを追加する提案。
ファイルシステムからディレクトリやファイルの一覧を取得する操作はコストが高いので、キャッシュしておきたい。しかし、下手なキャッシュは問題になる。
キャッシュ機能は、TS時にはあったが削られた。削る際、将来的に考察するとされていた。この提案はその考察である。
[PDF] P0318R0: decay_unwrap and unwrap_reference
decay_unwrapとunwrap_referenceの提案。
unwrap_reference_t<T>は、もしTがreference_wrapper<X>の場合、X &になる。decay_unwrap_t<T>は、もしdecay_t<T>の結果がreference_wrapper<X>の場合、X &になる。
つまり、reference_wrapperをunwrapするためのtraitsだ。reference_wrapperは標準ライブラリにおいて特別な扱いを受けていて、unwrapして扱う挙動になっているライブラリがいくつかある。それならば、標準でunwrapするtraitsが提供されているべきである。
[PDF] P0319R0: Adding Emplace functions for promise<T>/future<T>
future/promiseに対してemplaceを追加する提案。
ドワンゴ広告
ドワンゴは本物のC++プログラマーを募集しています。
CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0