本の虫

著者:江添亮
ブログ: http://cpplover.blogspot.jp/
メール: boostcpp@gmail.com
Twitter: https://twitter.com/EzoeRyou
GitHub: https://github.com/EzoeRyou

アマゾンの江添のほしい物リストを著者に送るとブログ記事のネタになる

筆者にブログのネタになる品物を直接送りたい場合、住所をメールで質問してください。

C++標準化委員会の文書: P0550R0-P0601R0

興味深いものだけ解説。

[PDF] P0550R0: Transformation Trait uncvref

decayとよく似たtraits、uncvrefの追加。

uncvref<T>::typeはTからCV修飾子とリファレンスを取り除いた型になる。decay<T>::typeとは違い、配列からポインター、関数から関数ポインターへの変換は行わない。

あるべきだ。

[PDF] P0551R0: Thou Shalt Not Specialize std Function Templates!

std名前空間内の関数テンプレートはユーザーが特殊化してはいけないというルールを作ろうと言う提案。関数テンプレートはC++11から特殊化できるようになったので、これまで考慮されてこなかった問題が出てきた。

[PDF] P0552R0:enable_if vs. requires

既存のenable_ifを利用した関数テンプレートに制約を与えるコードを、Concept Liteのrequires実装に置き換えてみたところ、Conceptによる制約付きテンプレートは、制約なしテンプレートよりもpartial orderingで優先されるため、オーバーロード解決の結果に違いをもたらすという警告。

文書では、std::swapをenable_if実装とrequires実装したものを比較して既存のテストに失敗したときの挙動の違いが驚きだったとしている。

既存のコンセプトを使わないコードにコンセプトを使うコードを混ぜると思わぬ挙動の違いに出くわすかもしれない。

P0553R0: P0553R0: Bit operations

ビットイテレーターが提案されているが、それを実装するために必要な基礎的なビット操作関数の追加。

rotl, rotr, popcount, countl_zero, countl_one, countr_zero, countr_oneの追加

rotlとrotrは左右へのロテート。popcountは1のビット数のカウント。countl_zeroは左から連続した0のビットのカウント、_oneは1のビットのカウントcountrは右から。

P0556R0: P0556R0: Integral power-of-2 operations

符号なし整数型に対して適用できる2の累乗に関係したフリー関数を追加する提案。

ispow2, ceilpow2, floorpow2, log2の追加。引数は符号なし整数型でなければならない。

ispow2(x)はxが2の累乗である場合trueを返す。ceilpow2(x)はx以上の最小の2の累乗数を返す。floorpow2はx以下の最大の2の累乗数を返す。log2は2が底のxの対数を返す。小数部は切り捨てられる

[PDF] P0557R0:Concepts: The Future of Generic Programming

Bjarne Stroustrupによるコンセプトの解説。軽く解説(briefly explain)と言っておきながらこの分量はどうなのか。

[PDF] P0559R0: Operating principles for evolving C++

C++標準化の原則のガイドライン。

[PDF] P0562R0:Initialization List Symmetry

クラスのメンバー初期化子の末尾に余計なコンマがあっても許す提案。enumと似ている。

class C
{
    int a, b, c ;
public :
    C( int x, int y, int z ) :
        a(x),
        b(y),
        c(z), // 最後に余計なコンマが付いているが許す
    { }
}

まあ、入れてもそれほど問題にはならないだろうが、今更入れるべきことだろうか。

[PDF] P0563R0:Vector Front Operations

今は昔、賢者たる男女らは非効率的なコードを書く定めの卑しき我らを救い給うために標準テンプレートライブラリを作り給いき。しかるに、賢者は長生なる魔法使いにのみ許されたる危うげなる魔術を我らの前から隠し給いき。天旋り日転じて、田舎の若人に至るまで幾年もの魔術の鍛錬を積むこと久しく、まさに黒魔術をつまびらかにせんとする日、来たれり。何をいいたいかというと、vectorのpush_frontとpop_frontのことだ。

vectorにpush_frontとpop_frontがない理由は、O(N)の非効率的な操作だからだ。vectorへの先頭へのinsertやeraseは、残りの要素をすべて1つづつずらす必要がある。

ところで、最近のハードウェアの事情はすっかり変わってしまった。もはや見かけ上のオーダーより、データの局所性の方が重要になってしまった。局所性のあるデータを隣接するメモリにずらす操作より、メモリ確保の方がはるかにコストのかかる処理となってしまった。

実際、マイクロベンチマークでも先頭へのinsertやeraseは、vectorの方がlistやdequeより速い。

そこで、もはやvectorにpush_frontやpop_frontを付けない理由はない。

ちなみに、vectorにpush_frontとpop_frontをつけると、std::queueの内部コンテナーとして使うことができる。

P0564R0: P0564R0: Wording for three-way comparisons

operator <=>の文面案。

[PDF] P0565R0:Prefix for operator as a pack generator and postfix operator[] for pack indexing

pack-like(パック風)なものを生成するfor式と、packの中からインデックスで要素やサブパックを取り出す式の提案。


template < typename ... Types >
void f( Types ... args )
{
    // 4つめのパラメーターを取り出す
    std::cout << args[3] << std::endl ;
}


int main()
{
    // f(1,2,3,4,5,6,7,8,9)と同じ
    f( for( int i = 1 ; i != 10 ; ++i ) i... ) ;
}   

便利だ。最近、パラメーターパックを第一級市民として扱おうと言う提案が多く見られる。

P0572R0: p0572r0: bit_sizeof and bit_offsetof

ビットフィールドメンバーのビット数を取得できるbit_sizeofとビットフィールドメンバーのクラスの先頭アドレスからのオフセットを取得できるbit_offsetの提案。


struct Foo {
   uint8_t A : 2;
   uint8_t B : 4;
   uint8_t C : 1;
   uint8_t D : 1;
};

int main()
{
    bit_sizeof(Foo::B) ; // 4
    bit_offsetof(Foo::B) ; // 先頭アドレスからのビット数のオフセット
}

ほしい。

P0573R0: abbreviated lambdas

lambda式を使いやすくするために3つの機能を追加。

まず=> expr

// []( auto && x ) -> decltype(expr) { return expr ; }
// と同等
[]( auto && x ) => expr ;

引数の型名省略

// []( auto && x ) => x 
// と同等
[]( x ) => x ;

オーバーロード不可能な単項演算子>>

// static_cast<decltype(x)>(x)
// と同等
(>>x) ;

これはstd::forwardを楽に書くための記法。

[PDF] P0577R0:Keep that Temporary!

一時オブジェクトの寿命を延長するための機能の提案。registerキーワードを再利用する。

この提案は、register exprというregister式を追加する。register式によって、式の結果の一時オブジェクトの寿命はその書かれている文脈のブロックスコープの終わりまで延長される。register式はブロックスコープ内にしか書けない。

以下のようなコードが可能になる。


std::mutex mtx ;

void f()
{
    register std::lock_guard(mtx) ;
    std::string_view = register std::to_string(42) ;
}

lock_guardは変数を束縛するかムーブ代入しておかないと、一時オブジェクトの寿命が尽きてmutexがunlockされてしまう。問題はその変数自体は使わないので冗長な記述が必要になってしまう。

auto ref = std::lock_guard(mtx) ;

to_stringの結果は一時オブジェクトだが、これをstring_viewで受けてしまうと、直接参照で束縛したわけではないので、寿命が尽きてしまう。register式が役に立つ。

一時オブジェクトの寿命を延長する機能は以前にも提案されたが、ライブラリの実装にしか役に立たない仕組みだった。これならばユーザーも使うことができる。

[PDF] P0589R0:Tuple-based for loops

tupleの各要素にrange-based forの文法でアクセスできる機能の提案。ループというよりは展開だ。tupleコンセプトを満たしたものがrange-base forで展開可能になる。

今のConcept Liteが気に入らない。

P0592R0: To boldly suggest an overall plan for C++20

明らかにスタートレック信者が書いたらしきC++20の計画。以下の項目について注力する。

筆者はコンセプトLite提案を気に入っていないのでコンセプトについては懐疑的だ。

そんなことよりUnicode対応が必要だと思うのだが。

P0593R0: What to do with buffers that are not arrays, and undefined behavior thereof?

mallocで確保したメモリにオブジェクトを構築したものは配列ではないので配列としてアクセスするとC++の規格上未定義の動作になるが、実際そのような処理は書かれている。どうすべきかという問題提起。

P0595R0:The "constexpr" Operator

constexpr演算子の提案。コンパイル時に評価されているかどうかを見分けることができる。

例えば、コンパイル時にはポータブルなコードで計算しないといけないが、実行時には実装依存の高速な方法で計算できるような処理があった場合に、constexpr演算子によってコンパイル時評価されているかどうかで条件分岐できる。


constexpr double power( double d, int x )
{
    if ( constexpr() )
    {
    // コンパイル時評価されているのでポータブルな実装
    }
    else
    {
    // 実行時に評価されているので最適な処理を実行時ライブラリに任せる
        return std::pow( d, static_cast<double>(x) ) ;
    }
}

P0596R0:std::constexpr_trace and std::constexpr_assert

コンパイル時printfとしてのconstexpr_traceとコンパイル時assertとしてのconstexpr_assertの提案。コンパイル時に評価された時にコンソールにメッセージを出力する方法が提供される。

constexpr_assertの存在理由はよくわからない。static_assertがあれば十分ではないか。

P0597R0: std::constexpr_vector<T>

コンパイル時計算の中でも使えるmutableなconstexpr_vector<T>の提案。もちろんpush_backもできる。

[PDF] P0599R0:noexcept for Hash Functions

std::hashの数値、ポインター、標準ライブラリに対する特殊化は例外を投げるべきではないのでnoexceptにしろというアメリカNBからの要求コメント。わかる。

[PDF] P0600R0:applying [[nodiscard]] for C++17

[[nodiscard]]を追加する標準ライブラリの策定。malloc, async, launder, allocateにつける。

これで興味深い文書はすべて解説した。リフレクション周りの文書は無視した。

ドワンゴ広告

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

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

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