2014-12-29

近況

私の住んでいる妖怪ハウスに海外から不思議な荷物が贈られてきた。宛名はRYOU EZOEになっている。

開けてみると、DON'T TRACK USと書かれたTシャツが入っていた。

おそらくは、Don't Track Us T-Shirt – Duck Duck Goではないかと思われる。

29日は秋パンに今年最後のボルダリングに行く。

30日は、青春18切符で京都まで移動する予定だ。

どうも最近、C++以外のブログ記事がおろそかになってしまっているようだ。なにか書こうと思ったが、夜も遅いのでもう寝なければならず、長文が書けない。

2014-12-24

C++14の新機能の解説を戻り値の型推定まで書いた

年末だというのに忙しくC++14の新機能の参考書を書いている。とりあえず関数の戻り値の型推定まで書いた。

巻末: C++14の新機能

C++11: Syntax and Feature

もちろんクールなキッズが皆使うというGitHubで管理している。

EzoeRyou/cpp14-appendix

EzoeRyou/cpp-book

ところで、興味深いニュースがあるようだ。

ドワンゴ、IT技術書出版新ブランド「アスキードワンゴ」を設立 - 週アスPLUS

IT技術書出版ブランド「アスキードワンゴ (ASCII DWANGO)」立ち上げのお知らせ|ニュース|広報情報|株式会社ドワンゴ

2. C++11/14の参考書(仮題)

ドワンゴ所属のエンジニアによるC++11/14の文法と機能についての解説書です。

ドワンゴ所属のエンジニア、はて。C++11/14の解説書、はて。

紙に印刷された本の需要はどのくらいあるのだろうか。

ドワンゴ広告

この記事はドワンゴ勤務中に執筆した。

今日も有給取得者が多い様子。今夜もドワンゴのボルダリング部の恒例のボルダリングに行く予定。

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

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

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

2014-12-22

C++14の新機能の解説

C++11のコア言語の参考書をすでに書いたが、時代はすでにC++14になっている。C++14の新機能の参考書も書きたいが、既存の参考書を更新するのは骨が折れる。

そこで、C++14の新機能だけを解説する短い文書を巻末という形で書くことにした。まだ執筆途中だが、GitHubで公開しながら編集することにした。

EzoeRyou/cpp14-appendix

巻末: C++14の新機能

ドワンゴ広告

この記事はドワンゴ勤務中に書かれた。

今日は社内に人が少ない。有給取得者が多そうだ。

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

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

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

2014-12-21

各言語のARVv7とx86-64での実装のパフォーマンス比較

LPATHBench/writeup.md at master · logicchains/LPATHBench

同じ箇所に二回訪れずに最も長い経路を見つけるコードで。各言語の実装を、ARMv7とx86-84においてベンチマークしてみた結果が公開されている。

記事に書いてあるように、これは、ARMv7とx86-64のプロセッサーのベンチマーク比較ではなく、各言語の実装が、ARMとx86-64でどれだけ効率的に実装されているのかを比較している。

たとえば、C++はARMにおいてはx86-64の74%のパフォーマンスを出している。しかし、ARM版OpenJDKはなんと29%の速度しか出ていない。OracleによるJava実装は、40%ぐらいのパフォーマンスを出している。

コードはとても短いが、パフォーマンス改善のためのpull requestがどんどんよせられたらしく、その結果が興味深い。Javaでクラスではなく配列を使うようにしたら速くなったとか、C#のイテレーターは結構オーバーヘッドがあるだとか。

luajitが恐ろしく速いのが興味深い。

2014-12-19

.git/configが書き換えられるgitの脆弱性

WindowsとMac OS X用の公式gitクライアントの脆弱性により、.git/configが書き換えられ、任意のコマンドが実行されてしまう問題が修正されたようだ。

ANNOUNCE Git v2.2.1 and updates to older maintenance tracks

何が問題なのかというと、WindowsやMac OS Xのファイルパスの取り扱いで、異なるが同一として扱われる文字があることだ。

たとえば、Windowsでは、".git~1/config"というファイルパスは、".git/config"というファイルパスと同等のものとして扱われる。Mac OS XのHFS+でも、U+200cのような文字が無視されるので、".g/u200cit/config"が、".git/config"と同等に扱われる。

この結果。そのような名前のレポジトリをcloneしたWindowsやMac OS X環境では、.git/configが上書きされ、任意のコマンドを実行可能になってしまう。

GNU/Linuxでcase-sensitiveなファイルシステムを使った環境では、この問題には影響されない。

修正内容として、WindowsとMac OS X環境では、そのような一部の特殊な文字を拒否するようになったということだ。また、GNULinuxのような環境やでも、クロスプラットフォーム対応のため、そのような文字を拒否するオプションが追加されたそうだ。

2014-12-18

12月25日、妖怪ハウスでケーキ会、12月27日にボドゲ会

特に何をする予定もないし、何も用意はしないが、年末は暇なので、妖怪ハウスで消極的に人を集めてみようと思う。

12月25日はクリスマスなので、妖怪ハウスにケーキでも用意しておこうと思う。

12月27日は、今年最後のボードゲーム会を開きたいものだ。

人が集まるかどうかはわからないが、告知だけしておく。

妖怪ハウスの住所は、中野区野方5-30-13 ヴィラアテネ401となる。


View Larger Map

2014-12-17

プレシジョンダイス

筆者は、ダイスの目にはさんざん悩まされてきた。多くのボードゲームではダイスを使う。問題は、そのダイスの目が明らかに偏っているのではないかということが度々起こるからだ。

例えばカタンだ。カタンでは、六面ダイスを二個使い、目の合計によって該当する土地の資源を得る。六面ダイスを二個振った目の合計値の確率は、2と12が最も少なく1/36、7が最も多く21/36となっている。ところが、今まで経験したカタンでは、よく出るはずの6,7,8がなかなか出なかったり、なかなか出ないはずの2や12が多く出たりすることがたびたびあった。

これは、ダイスの加工精度の問題である。ダイスの加工精度に問題があると、当然出目も偏ってくる。

プレシジョンダイスと呼ばれているものがある。表面に目の凹みがなく、よく研磨されている加工精度のいいダイスである。今、プレシジョンダイスを買うには、どうやらバックギャモン協会のWebサイトから購入するのが手っ取り早いようだ。

プレシジョンダイス - SHOP | 日本バックギャモン協会

そこで、実際に購入してみた。ついでにダイスを降る際も、ダイスカップとダイストレイを利用するようにしてみた。

先週から何度かカタンや街コロをしているが、ダイスの出目に違和感のある偏りは見られなかった。

これから六面ダイスを使うボードゲームの際には積極的に使っていきたい。

2014-12-16

C++14に入る機能テストマクロの一覧

現実のコンパイラーにおいて、C++11やC++14、そして今制定されようとしている各種TSやC++1zなどの機能は、個々に実装される。その場合、あるコンパイラーのあるバージョンは、rvalueリファレンスを実装している、その次のバージョンはconstexprを実装したという、中途半端に機能を実装した状態になる。

その結果、現実には、往々にして以下のようなコードが書かれることになる。

#ifndef __USE_RVALUE_REFERENCES
  #if (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 3) || \
      _MSC_VER >= 1600
    #if __EDG_VERSION__ > 0
      #define __USE_RVALUE_REFERENCES (__EDG_VERSION__ >= 410)
    #else
      #define __USE_RVALUE_REFERENCES 1
    #endif
  #elif __clang__
    #define __USE_RVALUE_REFERENCES __has_feature(cxx_rvalue_references)
  #else
    #define __USE_RVALUE_REFERENCES 0
  #endif
#endif

標準規格としては、一部機能だけ実装することを推奨するのではないが、現実がこうである以上、ある機能が実装されているかどうかを調べる標準のプリプロセッサーマクロが存在するべきである。

そこで提案されているのが、Feature-testing recommendations for C++だ。

この提案では、C++の主要機能が実装されている場合、特定の名前のプリプロセッサーマクロが事前に定義されることとなる。例えば、rvalueリファレンスの場合、__cpp_rvalue_referencesという名前のプリプロセッサーマクロが定義される。

マクロの名前は、名前の衝突を避けるため、プレフィクスが付けられる。コア言語機能ならば__cpp_、ライブラリー機能ならば__cpp_lib_である。機能名は、その機能の論文のタイトルから採用される。

マクロの値は、その機能がドラフトに採用された年と月を表現している。これにより、標準規格策定中にドラフトが更新された場合、値も更新される。たとえば、C++11の機能である__cpp_rvalue_referencesの場合、2006年の10月にドラフト入りしたので、その値は200610となる。

特定のヘッダーファイルがあるかどうかを調べるプリプロセッサーの機能、__has_includeが追加される。これは、#ifや#elifの中で使うことができる。

#ifdef __has_include
#  if __has_include(<optional>)
#    include <optional>
#    define have_optional 1
#  elif __has_include(<experimental/optional>)
#    include <experimental/optional>
#    define have_optional 1
#    define experimental_optional
#  else
#    define have_optional 0
#  endif
#endif

機能テスト推奨に対応している実装で、#ifdefで__has_includeを記述すると、定義済みだと評価される。#ifや#elifで__has_include(ヘッダー)と記述すると、そのヘッダーが存在する場合はtrueとなる。

同様に、特定のattributeがあるかどうかを調べるプリプロセッサーの機能、__has_cpp_attributeが追加される。

#ifdef __has_cpp_attribute
#  if __has_cpp_attribute(deprecated)
#    define ATTR_DEPRECATED(msg) [[deprecated(msg)]]
#  else
#    define ATTR_DEPRECATED(msg)
#  endif
#endif

具体的なマクロ名

実際に論文を読めばいいと思うのだが、とりあえずここにも書いておく。ほとんどの機能は、このブログやC++11の参考書で解説したはずだが、まだ知らない読者はいるのだろうか。なにか新たに解説して欲しい機能があればコメントで言えば解説するつもりだ。

C++98機能

機能 セクション番号 マクロ名 ヘッダー
実行時型情報 5.2 __cpp_rtti 199711 predefined
例外 15 __cpp_exceptions 199711 predefined

C++11機能

文書番号 文書名 セクション番号 マクロ名 ヘッダー
N2249 ユニコード文字型 2.13 __cpp_unicode_characters 200704 predefined
N2442 生文字列リテラルとUnicode文字列リテラル 2.13 __cpp_raw_strings 200710 predefined
__cpp_unicode_literals 200710 predefined
N2765 User-defined Literals 2.13, 13.5 __cpp_user_defined_literals 200809 predefined
N2927 lambda式 5.1 __cpp_lambdas 200907 predefined
N2235 constexpr 5.19, 7.1 __cpp_constexpr 200704 predefined
N2930 Range-Based for 6.5 __cpp_range_based_for 200907 predefined
N1720 static_assert 7 __cpp_static_assert 200410 predefined
N2343 Decltype 7.1 __cpp_decltype 200707 predefined
N2761 属性(attribute) 7.6 __cpp_attributes 200809 predefined
__has_cpp_attribute(noreturn) 200809 predefined
__has_cpp_attribute(carries_dependency) 200809 predefined
N2118 rvalueリファレンス 8.3 __cpp_rvalue_references 200610 predefined
N2242 可変長テンプレート(Variadic Templates) 8.3, 14 __cpp_variadic_templates 200704 predefined
N2672 初期化リスト(Initializer List) 8.5 __cpp_initializer_lists 200806 predefined
N1986 コンストラクターのデリゲート 12.6 __cpp_delegating_constructors 200604 predefined
N2756 非staticデータメンバーの初期化子 12.6 __cpp_nsdmi 200809 predefined
N2540 継承コンストラクター 12.9 __cpp_inheriting_constructors 200802 predefined
N2439 リファレンス修飾子(*thisへのムーブセマンティクス) 13.3 __cpp_ref_qualifiers 200710 predefined
N2258 テンプレートエイリアス 14.5 __cpp_alias_templates 200704 predefined

C++14機能

まだこのブログで詳細に解説していない機能もあるはずだ。

文書番号 文書名 セクション番号 マクロ名 ヘッダー
N3472 2進数リテラル 2.14 __cpp_binary_literals 201304 predefined
N3781 シングルクオートによる数値区切り 2.14 __cpp_digit_separators 201309 predefined
N3648 汎用lambdaキャプチャー 5.1 __cpp_init_captures 201304 predefined
N3649 ジェネリックlambda式 5.1 __cpp_generic_lambdas 201304 predefined
N3778 サイズ付き解放関数 5.3, 18.6 __cpp_sized_deallocation 201309 predefined
N3652 constexpr関数の制限緩和 5.19, 7.1 __cpp_constexpr 201304 predefined
N3638 関数の戻り値の型推定 7.1 __cpp_decltype_auto 201304 predefined
__cpp_return_type_deduction 201304 predefined
N3760 [[deprecated]]属性 7.6 __has_cpp_attribute(deprecated) 201309 predefined
N3653 アグリゲート初期化とメンバー初期化子の同時利用 8.5 __cpp_aggregate_nsdmi 201304 predefined
N3651 変数テンプレート 14, 14.7 __cpp_variable_templates 201304 predefined
N3658 コンパイル時整数シークエンス(index_sequence) 20 __cpp_lib_integer_sequence 201304 <utility>
N3668 exchange()関数 20 __cpp_lib_exchange_function 201304 <utility>
N3670 tupleで型を指定できるget 20.2-20.4 __cpp_lib_tuples_by_type 201304 <utility>
N3887 テンプレートエイリアスを使ったtuple_element_t 20.3-20.4 __cpp_lib_tuple_element_t 201402 <utility>
N3656 make_unique 20.7 __cpp_lib_make_unique 201304 <memory>
N3421 greater<>のテンプレート実引数の省略 20.8 __cpp_lib_transparent_operators 201210 <functional>
N3462 std::result_ofをSFINAEフレンドリーにする変更 20.9 __cpp_lib_result_of_sfinae 201210 <functional>
N3545 integral_constantにconstexprなoperator ()を追加する変更 20.9 __cpp_lib_integral_constant_callable 201304 <type_traits>
N3655 エイリアステンプレートでメタ関数をラップして::typeを_tにする変更 20.9 __cpp_lib_transformation_trait_aliases 201304 <type_traits>
LWG 2112 is_finalの追加 20.10 __cpp_lib_is_final 201402 <type_traits>
LWG 2247 std::nullptr_t可動化を調べるis_null_pointer 20.10 __cpp_lib_is_null_pointer 201309 <type_traits>
N3642 chronoとstringに対するユーザー定義リテラルの追加 20.11 __cpp_lib_chrono_udls 201304 <chrono>
21.7 __cpp_lib_string_udls 201304 <string>
N3657 連想コンテナでkey_typeに変換可能な型から検索する機能 23.4 __cpp_lib_generic_associative_lookup 201304 <map>
<set>
N3644 Null Forward Iterators 24.2 __cpp_lib_null_iterators 201304 <iterator>
LWG 2285 make_reverse_iterator 24.5 __cpp_lib_make_reverse_iterator 201402 <iterator>
N3671 equal, mismatch, is_permutationで二つのrangeをとるオーバーロード 25.2 __cpp_lib_robust_nonmodifying_seq_ops 201304 <algorithm>
N3779 std::complexのユーザー定義リテラル 26.4 __cpp_lib_complex_udls 201309 <complex>
N3654 quotedライブラリ 27.7 __cpp_lib_quoted_string_io 201304 <iomanip>
N3659 shared_mutex 30.4 __cpp_lib_shared_mutex
__has_include(<shared_mutex>)
1 predefined
N3891 shared_mutexをshared_timed_mutexに改名 30.4 __cpp_lib_shared_timed_mutex 201402 <shared_mutex>

疲れた。

ドワンゴ広告

この記事はドワンゴ勤務中に書かれた。

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

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

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

Google Newsに強制課金する法律、あっけなく失敗

Spanish Newspaper Publishers' Association Now Asks Government To Help Stop Google News Closure | The Spain Report

スペインでは、Webサイトが報道機関のWebサイトをわずかでも引用する場合、報道機関に対し対価を支払わなければならないという法律を、報道機関のロビー活動により成立した。それを受けて、Googleは、Google Newsはそれ自体が金を生み出してはいないので、スペイン版を廃止すると宣言した。

どうやら報道機関のロビー団体はスペイン政府にGoogle Newsを廃止しないように何か行動をせよと言っているらしい。不思議なことだ。

ちなみに、ドイツでも同等の法律ができている。そのときもGoogle Newsは廃止を宣言した。その結果、Webトラフィックが激減したため、報道各社は、Googleと特別に取引して、Googleは対価を支払わなくてもよいということになった。その結果、Googleの独占的地位をますます強固たるものにしてしまった。

この件に関してはGoogleの方が役者は上だということだろう。

それにしても、市場をほぼ独占している最大手のGoogleが自らやめると宣言してくれたのだから、今から報道各社で検索サービスを開発して公開すれば、市場シェアを取れるはずだが、それはしないらしい。もちろん、Googleほどの効率を出すのは難しいだろうし、実際にGoogleが主張する通り、検索サービス単体は直接利益にならないのだろうが。

2014-12-14

Microsoftがbitcoinによる支払いを受け付けるらしい

How do I use Bitcoin with my Microsoft account?

Microsoftが米国でbitcoinによる支払いを受け付けるらしい。

なんともまあ、面白い流れだ。

2014-12-12

C++1zに採択された新機能

C++1zともC++17とも呼ばれているC++の次の規格には、まだ大きな機能は採択されていない。それでも、いくつかドラフト入りしている新機能はあるので、ここではその機能を紹介していく。

いつも通り、ここに書かれている内容はまだドラフト段階の機能であり、今後変更されたり、取り除かれたりする可能性もある。

N3928: メッセージ無しstatic_assert

C++11で追加されたstatic_assertには、文法上、必ず文字列リテラルを記述しなければならなかった。

static_assert( expr, "Captain Obvious To the Rescue! expr is false.") ;

この文字列リテラルは、実装が診断メッセージ(例えばコンパイラーのエラーメッセージ)に使うことができる。しかし、C++14までは、文字列リテラルが文法上必須で、必ず記述しなければならなかった。

そこで、文字列リテラルを記述しなくても良い文法が追加された。

static_assert( expr ) ;

N4086: トライグラフの除去??!

トライグラフが文面から削除された。

N4051: テンプレートテンプレートパラメーターにtypenameキーワード

C++14まで、テンプレートテンプレートパラメーターの文法は、classキーワードしか使えなかった。

template < 
    template < typename T >
    class U // typenameキーワードは不可
> struct X ;

typenameも使えるようになる。

template < 
    template < typename T >
    typename U // typenameキーワードが使える
> struct X ;

N4295: Fold式

パラメーターパックの中身すべてに対して演算子を適用したい場合、再帰的なテンプレートを書く必要がある。例えば、引数をすべてoperator +で合計する関数テンプレートを書くと、以下のようになる。

template < typename T >
T sum( T && t )
{
    return t ;
} 

template < typename T, typename ... Types >
T sum( T && t, Types && ... args )
{
    return t + sum( std::forward<Types>( args ) ... ) ;
}

いかにも面倒だ。やりたいことは、a1 + a2 + a3 + ... + aNということなのに、この記述はあまりにも冗長すぎる。

そこで提案されているのが、fold式だ。パラメーターパックpにたいして、(p + ...)と書くと、p1 + p2 + p3 + ... pNとパック展開してくれる。

fold式を使うと、以下のように書ける。

template < typename ... Types  >
auto sum( Types && ... args )
{
    return (args + ...) ;
}

fold式では、括弧は必須である。

template < typename ... Types  >
auto sum( Types && ... args )
{
    // エラー
    return args + ... ;
}

fold式には、left foldとright foldが存在する。

(... op e)は、left foldである。(e1 op e2) op e3) op e4のように展開される。

template < typename ... Types  >
auto sum( Types && ... args )
{
    return (... + args) ;
}

int main()
{
    // ((1 + 2) + 3) + 4
    sum( 1, 2, 3, 4 ) ;
}

(e op ...)は、right foldである。e1 + (e2 + (e3 op e4))のように展開される。

template < typename ... Types  >
auto sum( Types && ... args )
{
    return ( args + ... ) ;
}

int main()
{
    // 1 + ( 2 + ( 3 + 4 ) )
    sum( 1, 2, 3, 4 ) ;
}

fold式には、単項fold(unary fold)と二項fold(binary fold)が存在する。

上記の、(... op e)と(e op ...)は、単項fold式である。

二項fold式とは、(e1 op1 ... op2 e2)のことである。op1とop2は同じfold演算子でなければならず、e1とe2のどちらか片方のみが未展開のパラメーターパックでなければならない。

e2がパラメーターパックである場合、left foldになる。e1がパラメーターパックの場合、right foldになる。

template < typename ... Types >
void sum( Types && ... args )
{
    // binary left fold
    auto a = ( 0 + ... + args ) ;
    // binary right fold
    auto b = ( args + ... + 0 ) ;

    // エラー、両方がパラメーターパック
    auto c = ( args + ... + args ) ;
    // エラー、両方が非パラメーターパック
    auto d = ( 0 + ... + 0 ) ;
}

fold式に使える演算子はfold演算子である。これは以下の通り。

    +  -  *  /  %  ^  &  |  =  <  >  <<  >>
    +=  -=  *=  /=  %=  ^=  &=  |=  <<=  >>=
    ==  !=  <=  >=  &&  ||  ,  .*  ->*

パラメーターパックが空の場合、一部のfold演算子については、以下のようにデフォルトの値が定められている。

Table N. Value of folding empty sequences
Operator Value when parameter pack is empty
* 1
+ int()
& -1
| int()
&& true
|| false
, void()
template < typename ... Empty >
void f( Empty ... e )
{// eは空のパラメーターパックとする

    auto x1 = ( e * ... ) ; // 1
    auto x2 = ( e + ... ) ; // int()
    auto x3 = ( e & ... ) ; // -1
    auto x4 = ( e | ... ) ; // int()
    auto x5 = ( e && ... ) ; // true
    auto x6 = ( e || ... ) ; // false
    auto x7 = ( e , ... ) ; // void()
}

これ以外のfold演算子で、空のパラメーターパックをfold式でパック展開しようとすると、ill-formedになる。

N4267: u8文字リテラル

charひとつで表現できるUTF-8文字リテラル。

char A = u8'A' ; // 0x41

主な使い方として、確実にASCII文字の数値をわかりやすいリテラルでソースコードに記述できる。

N4230: 名前空間のネスト

namespace A { namespace B { namespace C {
} } }

を、

namespace A::B::C {
}

のように書ける。

N4266: 名前空間と列挙子に属性

名前空間と列挙子に属性を指定することができる。C++14までは、文法上の問題で指定できなかった。

具体的には、[[deprecated]]を指定できるようになった。

namespace [[deprecated("Use new_lib")]] lib { }
namespace new_lib { }

enum struct E { value [[deprecated("Use VALUE.")]], VALUE } ;

ドワンゴ広告

この記事はドワンゴ勤務中に書かれた。

今日は社内が盛り上がっていた。

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

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

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

2014-12-11

Tarse Range-Based forがClangから取り除かれていた

C++1zには、N3994: Tarse Range-based forが提案されていた。これは、Range-based forで型を書かずにすむようになる小粒な新機能だ。

任意のコンテナーを受け取って、その要素をすべて標準出力に出力する関数テンプレートを書くとする。これは以下のように書ける。

template < typename Container >
void print( Container const & c )
{
    for ( typename Container::value_type & elem : c )
        std::cout << elem << '\n' ;
}

いちいち型を書くのが面倒だ。これにはautoを使えばよい。

template < typename Container >
void print( Container const & c )
{
    for ( auto && elem : c )
        std::cout << elem << '\n' ;
}

しかし、auto &&すら書くのが面倒ではないか。N3994では、auto &&を省略できる新機能、Tarse Range-based forを提案していた。これはClangとGCCで実装されていたが、今試すとSNV HEADのClangでは動かない。はてどうしたことか。

調べると、C++1zには採用されない見込みになったので、取り除かれたそうだ。

[llvm-project] Revision 222865

ドワンゴ広告

この記事はドワンゴ勤務中に書かれた。

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

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

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

2014-12-10

2014-11-post-Urbanaのレビュー: N4332-N4339

N4332: Networking Library Proposal (Revision 3)

Boost.Asioを土台にしたネットワークライブラリの提案。

N4333: Concepts Lite

Concept Lite TSのドラフト

N4334: Wording for bool_constant

std::integral_constantのエイリアステンプレート、bool_constantの提案。既存のtrue_typeとfalse_typeはbool_constantで書き直される。

template <bool B>
using bool_constant = integral_constant<bool, B>;

typedef bool_constant<true> true_type;
typedef bool_constant<false> false_type;

新しいクラステンプレートではなくエイリアステンプレートなので、integral_constantを期待している既存のコードでも互換性の問題は生じないはずだ。

N4335: C++ Extensions for Library Fundamentals, Working Draft

標準ライブラリに対する拡張TSのドラフト

機能テストマクロ、optional, any, string_view, polymorphic_allocator, memory_resource, futureの拡張、新しいアルゴリズムなど

N4336: C++ Extensions for Library Fundamentals, Version 2, Working Draft

N4335とは異なるが、これも標準ライブラリに対する拡張TSのドラフト。

not_fn、observer_ptr, container_erasure, ostream_joiner, GCDとLCMなど。

N4337: Editor's Report — Library Fundamentals TS

標準ライブラリに対する拡張TSのドラフト編集者の報告書。

N4339: Agenda and Meeting Notice for WG21 Concepts Meeting

2015年1月26日にBloombergで行われるConcept会議の日程表。

ドワンゴ広告

この記事はドワンゴ勤務中に書かれた。

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

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

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

2014-11-post-Urbanaのレビュー: N4320-N4331

N4320: Make exception-specifications be part of the type system

例外指定を型システムに含める提案。

関数ポインターを経由した例外指定の偽装がコンパイル時に検出できるようになる。

void (*p)() throw(int);
void (**pp)() throw() = &p;   // エラー

struct S { typedef void (*p)(); operator p(); };
void (*q)() noexcept = S();   // エラー

N4321: Towards Implementation and Use of memory_order_consume

memory_order_consumeの効果とLinuxカーネルでは使いにくい問題点などを解説したうえで、Linus Torvaldsでも満足する機能を設計している。

N4322: Linux-Kernel Memory Model

LinuxカーネルにおけるメモリモデルをC++の規格と比較してまとめたもの。

N4323: Out-of-Thin-Air Execution is Vacuous

複数のスレッドからのメモリアクセスによって競合を起こした場合、まったく脈絡のない値が現れることが規格上許されている。しかし、全く脈絡のない値が現れるのは問題である。この虚空から現れいでたる(Out-of-Thin-Air)値についての具体例の考察。

N4324: Use Cases for Thread-Local Storage

タイトル通り、TLSの利用例

TLS(Thread Local Storage)は長年利用されているにもかかわらず、その必要性が一般に理解されていない。C++標準化委員会の会議においてすら、TLSの存在価値に懐疑的な意見が出された。SIMDやGPGPUの専門家はTLSの存在意義に懐疑的で、逆にベクトルループ内でTLSが正しく動かないことに不満を持つものもいる。

この文書はその意見に答えて、TLSの既存の利用例や、SIMDやGPGPUにおけるTLSサポートの難しさ、TLSの代替機能などを考察している。

TLSの利用例として、例えばLinuxカーネルでは、CPUごとに必要な変数としてTLSを用いている。CPUごとに500以上もの静的なTLS変数と、100以上の動的なTLS変数が存在する。

TLSの最も主要な利用例としては、統計カウンターである。スレッドごと、CPUごとにカウンターを分割して、個別にカウンターを更新した後、最後に加算してすべてのスレッドのカウンターの値を得る。

TLSの他の利用例としては、オーバーヘッドの低いログやトレースを実装するために使われている。

TLSはメモリーアロケーターのスレッドごとのキャッシュにも使われている。

等など

なぜTLSはSIMDやGPGPUでは問題になるのか。TLSを初期化、破棄するにはコストがかかる。特にTLS変数がコンストラクターやデストラクターを持つ場合は、ミリ秒単位の時間が使われるかもしれない。これは、ひとつの実行単位がマイクロ秒単位のSIMDにとっては、無駄が多すぎる。GPGPUの実行単位はもう少し長いが、それでも問題だ。GPGPUの場合は、実行媒体が非常に多いので、GPGPUスレッドごとにTLS変数を作るのは、メモリーフットプリント上好ましくない。

TLSとSIMD/GPGPUは共存できるのか。SIMDレーンごとにTLS変数を初期化破棄するのはいかにも無茶だ。しかし、SIMDベクトルループ内でTLS変数の利用を禁止すると、従来のライブラリ、とくにerrnoに依存するようなライブラリが軒並み使えなくなってしまう。

N4325: C++ Standard Evolution Active Issues List
N4325: C++ Standard Evolution Completed Issues List
N4337: C++ Standard Evolution Closed Issues List

C++に提案中の新機能に対する議論中の問題、解決済みの問題、却下された問題の一覧。

N4328: C++ Standard Library Issues History for C++14

標準ライブラリのC++14に対する更新履歴の一覧。なかなか新しい文書だ。さすがに更新履歴が長くなってきたから分離したのだろうか。

N4329: C++ Standard Library Active Issues List
C++ Standard Library Defect Report List
N4331C++ Standard Library Closed Issues List

標準ライブラリで議論されている問題、解決済みの問題、却下された問題の一覧。

ドワンゴ広告

この記事はドワンゴ勤務中に書かれた。

ドワンゴにはボルダリング部があり、毎週水曜日に部員は仕事後にボルダリングに行っている。

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

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

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

2014-12-09

2014-11-post-Urbanaのレビュー: N4310-N4319

N4310: Technical Specification for C++ Extensions for Parallelism, Working Draft

Parallelism TSのドラフト

[PDf] N4311: Parallelism TS Editor's Report

Parallelism TSの編集者の報告書

[PDF] N4312: Programming Languages -- Technical Specification for C++ Extensions for Parallelism

N4311と内容は同じ。

N4313: Improvements to the Concurrency Technical Specification, revision 1

<future>にwhen_all, when_any_result, when_any, make_ready_future, make_exceptional_futureを追加する提案。

N4314: Data-Invariant Functions (revision 2)

入力の値におって、処理時間が異なるなどの外部から計測可能な挙動の違いが存在する場合、外部からその違いを計測することによって、秘密の情報が漏れてしまうことがある。暗号処理の実装において、サイドチャネル攻撃として知られている問題だ。

最近のOpenSSLのパッチは、そのような問題に対処するために入力によって処理速度が変化しないようにプラットフォーム依存の方法で対処している。

そのような仕組みは標準に存在するべきである。この論文では、入力の値によって外部から計測可能な挙動の変化が生じないような基本的な演算を提供するライブラリ、std::constant_time::value<T>を提供している。

// 入力の値によって処理時間やメモリアクセスパターンに差がでないことが保証されている
auto equal( std::constant_time::value<int> a, std::constant_time::value<int> b )
{
    return a == b ;
}

N4315: make_array, revision 3

std::arrayを作るstd::make_arrayの提案。

// 面倒
std::array<int, 5> a1 = { 1, 2, 3, 4, 5 } ;
// 簡単
auto a2 = std::make_array( 1, 2, 3, 4, 5 ) ;

// 面倒
atd::array<char, 4> a3 = { 'a', 'b', 'c', '\0' } ;
// 簡単
auto a4 = std::to_array("abc") ;

// std::array< char const *, 1 >
auto a5 = std::make_array("abc") ;

これは自分で実装してみるとVariadic Templatesの練習になって面白い。

リファレンス実装が公開されている。

N4316: std::rand replacement, revision 2

std::randの代替品、std::randintの提案

前回の変更点は、seed関数がseed_initからreseedに解明されたことだ。

[PDF] N4317: New Safer Functions to Advance Iterators

イテレーターを進めるadvanceとnextとprevに終端をチェックする安全版を追加する提案

例えば、イテレーターを三つ進めるごとに処理をしたいとする。以下のように書くと問題がある。


for ( auto i = begin(con), e = end(con) ; i != e ; std::advance( i, 3 ) ) 
    process( *i ) ;

このループは、イテレーターを三回進めるごとに終端のチェックを行っている。イテレーターの指す要素の数によっては、終端を飛び越してしまう可能性がある。

終端をチェックしつつイテレーターを進めるadvance, next, prevを追加しようという提案。この提案を使えば、以下のように書ける。


for ( auto i = begin(con), e = end(con) ; i!= e ; std::advance( i, e, 3 ) )
    process( *i ) ;

advance, next, prevに、終端のイテレーターを取るオーバーロードが追加される。

[PDF] N4318: Proposal to add an absolute difference function to the C++ Standard Library

絶対値の差を計算するabs_diff(a, b)の提案。

operator <とoperator -をサポートする型のオブジェクトの絶対値の差を計算してくれる。

int main()
{
    // 2
    std::cout << abs_diff( 3, 5 ) << '\n' ;
}

従来のabsでこれをやろうとすると、abs(a - b)のようになる。しかし、もし型が符号なし整数型で、bの方が大きい場合、悲惨なことになる。


int main()
{
    std::cout << abs( 3 - 5 ) << '\0' ;
}

結果は好ましい物にならないだろう。

[PDf] N4319: Contracts for C++: What are the Choices

会議の結果、contract programming(契約プログラミング)をコア言語で直接サポートすべきという意見に固まったが、contractに対するそれぞれの意見や経験がバラバラである。Microsoftの既存の経験から、contractの土台を解説している。

なぜcontractが必要なのか。

  • 実行時チェックによって予期しないプログラムの挙動を早期に発見できる
  • テストのサポート
  • 関数とデータ構造のドキュメント
  • 静的に証明可能な契約による最適化
  • 静的解析によるコンパイル時にバグの発見

contract systemに求めるもの

  1. あるコードに対する要求(required)と保証(ensured)を直接表現できること。たとえば、関数を呼び出す前と呼び出した後の条件や、通常時と異常時の挙動など。
  2. アノテーションによるオーバーヘッドを最小化する。contractは既存の機能と強調して働き、将来の発展を妨げるものであってはならない。
  3. 静的と動的な解析ツールや、コンパイラーの最適化の役に立つ
  4. あまりに冗長な文法ではないこと

論文著者は、contractが受け入れられるには、軽量な文法であることが必要であるとしている。

論文は、既存のマイクロソフト製品におけるContract機能を紹介している。

.NETのCodeContracts

public void TurnReactorOn()
{
    Contract.Requires(this.state == State.Off);
    Contract.Ensures(this.state == State.On);
    ...
}

このコードは、関数が呼び出される前はreactorが動いていないことを要求し、関数が呼び出された後はreactorが動いていることを保証するものである。これはライブラリで実装されている。実行時のチェックと、静的解析ツールによるチェックが行われる。

SAL

SALはプリプロセッサーマクロを多用した契約の記述だ。

void * memcpy(
_Out_writes_bytes_all_(count) void *dest,
_In_reads_bytes_(count) const void *src,
size_t count
);

この宣言は、destに書き込まれるバイト数とsrcから読み込まれるバイト数のアノテーションだ。MSはSALにより数多くのバグを発見して修正できているとしている。

System C#

System C#はC#の拡張で、言語機能としてcontractをサポートしている。

public string Format(int x)
requires x >= 0
ensures return != null
{
...
}

このコードは、関数が呼び出される前に、xが0ではないことを要求し、関数の戻り値がnullではないことを保証している。

ドワンゴ広告

この記事はドワンゴ勤務中に書かれた。

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

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

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

2014-11-post-Urbanaのレビュー: N4301-N4309

[PDF] N4301: Working Draft, Technical Specification for C++ Extensions for Transactional Memory

トランザクショナルメモリーのTSドラフト

[PDf] N4302: Technical Specification for C++ Extensions for Technical Specification for C++ Extensions for Transactional Memory

N4301とほぼ同一。

N4303: Pointer safety and placement new

以下のコードは、C++14で挙動が定義された。

#include <new>
#include <cassert>

struct A { char buf[1]; };
struct B { char buf[1]; };

int main(void) {
    A a{ { 0 } };
    B *bp = static_cast<B *>(static_cast<void *>(&a));
    new (bp) B{ { 1 } };
    assert(bp->buf[0] == 1);
}

C++14では、static_castはaの先頭アドレスを指すことが明記されたので、上のコードは動作する。

ただし、これによって、コンパイラーのポインターの値によるエイリアシングの判定に誤りが生じる。そこで、この論文では、launderという関数を追加している。この関数にポインターの値を通すことによって、コンパイラーのアドレス値の解析を阻止するのだとか。

template <typename T> constexpr T* launder(T* p) noexcept;
Required behavior: An invocation of this function may be used in core constant expressions whenever the value of its argument may be used in a core constant expression.

Requires: p represents the address A of a byte in memory and an object Obj whose cv-unqualified type is remove_cv_t<T> is located at the address A.

Returns: A value of type T * which points to Obj.

そういう明示的なものが使われるとは思えない。

N4304: C++ Standard Core Language Active Issues
N4305: C++ Standard Core Language Defect Reports and Accepted Issues
N4306: C++ Standard Core Language Closed Issues

コア言語で現在議論中の問題、解決済みの問題、却下された問題の一覧。

[PDF] N4307: National Body Comment -- ISO/IEC PDTS 19568 -- Technical Specification: C++ Extensions for Library Fundamentals

Library Fundamentals TSに対するNBコメント集。日本からはmake_applyの追加というコメントが出ている。

[PDF] N4308: National Body Comment -- ISO/IEC PDTS 19570 -- Technical Specification: C++ Extensions for Parallelism

Parallelism TSに対するNBコメント集。

Return type deduction for explicitly-defaulted and deleted special member functions

特別なメンバー関数をdefault化、delete定義するときに、戻り値の型推定を許す提案。

以下のコードが、

struct X
{
    X & operator = ( X const & ) = default ;
    X & operator = ( X && ) = delete ;
}

以下のように書ける。

struct X
{
    auto operator = ( X const & ) = default ;
    auto operator = ( X && ) = delete ;
}

うーん・・・・、なんとも言いがたい。あって邪魔にはならない機能だが。

ドワンゴ広告

この記事はドワンゴ勤務中に書かれた。

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

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

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

2014-12-08

2014-11-post-Urbanaのレビュー: N4293-N4298

N4293: C++ language support for contract programming

contractを言語でサポートする提案で、Urbanaの会議で議論した方針の結果をまとめたもの。

contractとは、処理を実行する上での前提条件(古典的にはassertマクロなどでチェックされていたもの)、処理を実行したあとの状態の保証、ある型の値は有効な状態になっていることだ。

これらのcontractは、既存のコードでは、assertマクロや、戻り値や例外などのエラー処理で処理されたりするものもあれば、単に未定義の状態になるとして済ませているものもある。

現在議論中のcontractは、コア言語によるサポートを必要とするものだ。ライブラリによる実装では、関数の本体の中に隠れてしまい、コンパイラーやツールからは使いにくくなってしまう。

ビルドモード(デバッグビルドやリリースビルドなど)を規格に含めるかどいうかという議論では、この提案では含めないということになった。

論文で提示されている文法は、提案する機能を示す目安であって、具体的な提案ではないが、例えば以下のような機能が欲しいとしている。

double square_root( double x )
expects( x >= 0.0 )
ensures( square_root >= 0.0 )

この例では、square_rootという関数のdouble型の実引数xは、必ず0.0以上であることを前提条件としていて、この関数の戻り値は必ず0.0以上であることを保証している。ensuresの中で関数名を使うと、関数の戻り値の意味になる。

これはあくまでこのような機能が欲しいという例示のための文法だ。

N4294: Arrays of run-time bounds as data members

実行時にサイズの決まる配列をクラスのデータメンバーとして持つことができる機能の問題点の洗い出しと解決案。

自動ストレージ、つまりスタックから実行時に決定されるサイズのストレージを確保したいという需要はあるが、C++風に型システムの上にサポートするには色々と問題があり、C++14では頓挫した。

既存の方法としては、alloca()とかC99のVariable Length Array、Flexible Array Memberなどがある。

int good_old_C()
{
    // スタックから確保
    // 低級すぎる
    void * p = alloca(100) ;
}

// C99
void vla( std::size_t size )
{
    // Variable Length Array
    // クラスによるラップができない
    char buf[size] ;
}

// C99
// Flexible Array Member
struct FAM
{
    std::size_t size ;
    char buf[] ;
} ;

void fam( std::size_t size )
{
    FAM * ptr =(FAM *) std::malloc( size ) ;
    ptr->size = size ;
}

C++でも実行時サイズ配列をサポートしたいが、型システムの中でやりたい。

前回の提案は、クラスの最後のデータメンバーが実行時サイズ配列で、クラスの最初のデータメンバーがconstな整数型でなければならず、最初のデータメンバーが実行時サイズ配列の要素数の指定に使われ、最初のデータメンバーの初期化が特別に扱われるというものだった。

// 前回の提案
struct X
{
    std::size_t size ;
    char buf[] ;

    X( std::size_t size ) : size(size), buf[size] { }
} ;

sizeの初期化は、通常のメンバーの初期化とは別に扱われる。

今回の提案では、配列コンストラクターという文法を提案している。

// 実行時サイズオブジェクト
struct X
{
    // 配列コンストラクター
    X[]() : buf[10] { }
    X[]( std::size_t size ) : buf[size] { }

    char buf[] ; // 実行時サイズ配列
} ;

配列コンストラクターはinlineでなければならない。

配列コンストラクターから通常のコンストラクターに転送することもできる。これはC++11の機能だ。

struct X
{
    // 配列コンストラクター
    X[]() : buf[10], X{} { }
    X[]( std::size_t size ) : buf[size], X{size1} { }

    // 通常のコンストラクター
    X() { }
    X( std::size_T size) { }

    char buf[] ; // 実行時サイズ配列
} ;

転送せずに、配列コンストラクターだけですべてを済ませることもできる。ただし、配列コンストラクターはinlineでなければならない。

今回の提案では、実行時サイズ型と実行時サイズオブジェクトに対してsizeofは一切サポートされない。

実行時サイズ配列の提案は文法や機能の設計がめまぐるしく変わっている。これもまだ決定ではないので、まだ変わるだろう。

sizeofがサポートされないのであれば、ある型が実行時サイズ型であるかどうかを調べるtraitsが欲しいところだ。

N4295: Fold expressions

Folding Expressionの文面案。

Folding Expressionとは、パラメーターパックpに対して、p + ...と書くと、p1 + (p2 + (p3 + p4))のように展開してくれる式のことだ。

例えば、実引数をすべて足し合わせる関数テンプレートsumを書きたいとする。従来ならば、以下のように書ける。

// 従来のパック展開による実装
template < typename T >
auto sum( T && t )
{
    return std::forward<T>(t) ;
}

template < typename T, typename ... Types >
auto sum( T && t, Types && ... args )
{
    return t + sum( std::forward<Types>(args) ... ) ;
}

見ての通り、極めて冗長だ。Folding Expressionを使えば、以下のように簡潔に書ける。

// Folding Expression
template < typename ... Types >
auto sum( Types && ... args )
{
    return args + ... ;
}

なお、ClangのSVNにすでに実装されているようだ。

Clang - C++1z, C++14, C++11 and C++98 Status

これはかなり確実に入りそうだ。

N4296: Working Draft, Standard for Programming Language C++

現在の最新のC++標準規格のドラフト

N4297: Editor's Report -- Working Draft, Standard for Programming Language C++

ドラフト編集者の編集報告書。

N4298: Agenda and Meeting Notice for WG21 Ballot Resolution Telecon Meeting

2014年12月5日に行われた電話会議の予定表。

ドワンゴ広告

この記事はドワンゴ勤務中に書かれた。

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

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

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

2014-11-post-Urbanaのレビュー: N4280-N4288

N4280: Non-member size() and more (Revison 2)

フリー関数として、size, empty, dataを追加する提案。

template < typename Container >
void f( Container c )
{
    size(c) ;
}

int main()
{
    vector<int> v = { 1, 2, 3 } ;
    f( v ) ;
}

[PDF] N4282: A Proposal for the World's Dumbest Smart Pointer, v4

スマートではないスマートポインター、observer_ptrの提案。

observer_ptrは、生のポインターのクラスによるラッパーである。unique_ptrやshared_ptrとは違い、observer_ptrはポインターを所有しない。論文では、生のポインターを使うより、コード上でポインターの利用がわかりやすくなると主張している。

N4284: Contiguous Iterators

連続したストレージ上を指すイテレーター、Contiguous Iteratorsの文面案。

Contiguous Iteratorsは、デリファレンスできるイテレーターaと整数値nにおいて、*(a + n)が、*(addressof(*a) + n)と同等になる。

この提案では、新しいイテレータータグを追加するようなことは、下位互換性を壊す恐れから行わない。単に文面上での規程にとどまっている。

標準ライブラリのうち、連続したストレージが保証されているコンテナーは、vector, string, valarray, arrayである。

N4285: Cleanup for exception-specification and throw-expression

例外指定の文面を修正する提案。文面の整理が目的で、意味上の変更はない。

[PDF] N4286: Resumable Functions (revision 3)

中断可能な関数をコア言語でサポートする提案。

[PDf] N4287: Threads, Fibers and Couroutines (slides deck)

スレッドとファイバーとコルーチンについての発表のため、Urbana会議で使われたスライド資料。

N4288: Strike string_view::clear from Library Fundamentals

string_view::clearを文面から削除する提案。

ドワンゴ広告

この生地はドワンゴ勤務中に書かれた。

社内ポータルが一通り完成してきたようだ。

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

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

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

2014-12-05

2014-11-post-Urbanaのレビュー: N4270-N4279

やはり欠番が多い。

N4270: Consolidated Revisions to C++ Extensions for Library Fundamentals

標準ライブラリに対する拡張。

  • std::functionのswapは、アロケーターは交換しないという文面の追加。
  • BM法による検索アルゴリズムの追加
  • optional
  • any

[PDF注意] N4272: Working Draft, Technical Specification for C++ Extensions for Transactional Memory

トランザクショナルメモリーのドラフト文面

N4273: Uniform Container Erasure (Revision 2)

一部のコンテナーは、効率化のため、eraseをメンバー関数として提供している。任意のコンテナーから汎用的かつ効率的に要素を削除できる、erase_if( container, pred )とerase( container, value )の提案

template < typename Container >
void remove_less_than_100( Container & c )
{
    // 100以下の要素を削除する
    std::erase( c, []( auto v ) { return v < 100 } ) ;
}

[PDF注意] N4274: Relaxing Packaging Rules for Exceptions Thrown by Parallel Algorithms - Proposed Wording (Revision 1)

N4157における並列アルゴリズムで例外をパッケージ化する際の制限緩和の修正案は十分ではなかったので、完全問題を修正する新しい文面案。

N4275: Parallelism PDTS Comment Responses

並列アルゴリズムのTSに対するNBコメントへの返答。日本からは4件送っている。

N4276: Adding Fused Transform Algorithms to the Parallelism TS

並列アルゴリズムとして、transform_reduce, transform_exclusive_scan, transform_inclusive_scanを追加する提案。

N4277: TriviallyCopyable reference_wrapper (Revision 1)

reference_wrapperをTrivially Copyableにする提案。

N4279: Improved insertion interface for std::{unordered_,}map (revised)

std::mapとstd::unordered_mapについて。

emplaceは、要素が存在するときは何もしないが、規格準拠な実装は実引数をムーブしてもよい。ムーブをしないことが保証されたtry_emplaceを追加する。

要素が存在しない時は挿入し、存在するときは代入する、insert_or_assignを追加する。

ドワンゴ広告

今日は軽い論文と欠番がが多かったのでだいぶたまっている論文を消化できた。

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

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

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

2014-11-post-Urbanaのレビュー: N4260-N4269

どうも欠番が多い。

N4261: Proposed resolution for Core Issue 330: Qualification conversions and pointers to arrays of pointers

多次元ポインターでconstを付け加える型変換について規定する文面がないため、以下のコードが違法になってしまう問題を修正する提案


  int main()
  {
     double *array2D[2][3];
  
     double       *       (*array2DPtr1)[3] = array2D;     // 合法
     double       * const (*array2DPtr2)[3] = array2DPtr1; // 合法
     double const * const (*array2DPtr3)[3] = array2DPtr2; // 違法
  }

規格の文面上にこの例についてカバーする箇所がないため、このようなことになってしまっている。

N4262: Wording for Forwarding References

テンプレート仮引数Tで実引数T &&や、auto &&は、どんな型でも受け取ることができる。この性質に対して、Fowarding Referenceという名前を付ける提案の文面案。

N4263: Toward a concept-enabled standard library

Concept Lite TSがほぼ完成したので、さっそく標準ライブラリをConceptに対応させたい。その対応させる際の方針を示した論文。

多少の非互換性は許容する方針らしい。たとえば、暗黙の型変換とか。

N4265: Transactional Memory Support for C++: Wording (revision 3)

トランザクショナルメモリーの文面案

この前のC++WG JPの会議では、現在提案中のトランザクショナルメモリーは、ハードウェアネイティブのトランザクショナルメモリーに落とし込める設計ではないので、何を考えて設計したのかよくわからない。全然実用的ではないという意見であった。

N4266: Attributes for namespaces and enumerators

名前空間とenumeratorにattributeを指定できる文法を追加する提案。これまでは文法が規定されていなかったので、deprecatedを指定できなかった。

namespace [[deprecated("lib_v1 is deprecated. Use lib_v2 instead.")]] lib_v1 { }

enum struct Option { safe, fast, super_fast, dangerously_fast [[deprecated("It has issues. Don't use it")]] } ;

N4267: Adding u8 character literals

charのオブジェクトひとつで表現できる文字に限ったUTF-8文字リテラルを追加する提案の文面案。

用途としては、ASCII文字をリテラルで表現できる。


char c = u8"c" ;

N4268: Allow constant evaluation for all non-type template arguments

非型テンプレート仮引数に配列からポインターへの型変換や関数からポインターへの型変換などを許容する提案の文面案

今回は欠番が多い。N4269のタイトルは、「まともなコンパイラーはatomicを最適化しない」というもので、興味深いのだが、欠番となっている。

ドワンゴ広告

この記事はドワンゴ勤務中に書かれた。

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

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

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

2014-11-post-Urbanaのレビュー: N4250-N4259

N4250: WG21 2014-10-24 Telecon Minutes

2014年10月24日に行われた電話会議の議事録。

N4251: WG21 2014-11 Urbana Minutes
[PDF注意] N4252: PL22.16 2014-11 Urbana Minutes

2014年11月の3-8日に行われたUrbana会議の議事録。

N4253: Language Support for Runtime Contract Validation (Revision 9)

高級なassertライブラリを追加する提案。

N4254: User-Defined Literals for size_t (and ptrdiff_t)

size_tとptrdiff_tのユーザー定義リテラルを<cstddef>に追加する提案。

#include <cstddef>
int x = 0 ; // int
int s = 0z ; // std::size_t
int p = 0t ; // std::ptrdiff_t

整数リテラルのデフォルトの型はintである。int型は符号付き整数型である。size_tやptrdiff_tは符号なし整数型である。size_tやptrdiff_tを扱うときに、整数リテラルをそのまま書いて演算や比較をしてしまうと、符号を混ぜて処理することになり、思わぬ誤りにつながる。そのため、型安全のためには、size_tやptrdiff_t型のリテラルがほしい。

N4255: Proposed resolution for US104: Allocator-aware regular expressions (rev 3)

正規表現ライブラリをアロケーターに対応させる提案。

Delimited iterators (Rev. 4)

本当の意味でのデリミターをサポートするostream_joinerを追加する提案。

ostream_iteratorに指定するデリミターは、実はサフィックスである。

vector<int> v = {1, 4, 6};
cout << "(";
copy(v.begin(), v.end(), ostream_iterator<int>(cout, ", "));
cout << ")"; // Oops! Prints (1, 4, 6, )

最後の要素の後にもデリミターが出力されてしまう。正しくデリミターを付加する、ostream_joinerを新たに追加する提案。

vector<int> v = {1, 4, 6};
cout << "(";
copy(v.begin(), v.end(), std::make_ostream_joiner(cout, ", "));
cout << ")"; // Prints (1, 4, 6) as desired

N4258: Cleaning up noexcept in the Library (Rev 3)

ムーブコンストラクターなど、標準ライブラリでnoexceptを必須にした関数でも、例外を投げたくなる状況がある。たとえばデバッグモードなど。そのため、規格の文面を、「例外を投げないことが推奨される」という文面に変える提案。

N4259: Wording for std::uncaught_exceptions

現在まだキャッチされていない例外の数を返すint std::uncaught_exceptions() noexceptの文面。

ドワンゴ広告

この記事はドワンゴ勤務中に書かれた。

社内で勃発したきのこたけのこ戦争はたけのこ陣営が勝利したようだ。解せないことだ。

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

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

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

2014-12-04

シェアハウスを作ってみたい

東京に来て、ほぼ一年たった。

東京に来てからこれまで、妖怪ハウスというシェアハウスに住んでいる。妖怪ハウスは住んでいて面白いところではあるが、職場から遠いという問題がある。各駅停車しか止まらない駅から電車に乗り、途中乗り換えを三回挟まなければ職場に到達できない。通勤時間も一時間はかかる。

どこか、職場の近辺にでも引っ越したいものだ。特に、ドワンゴでは、職場の5km圏内に住むと近距離手当が出る。歩いて通勤できる場所に住むというのは魅力的だ。

ただし、引越というものは、労力と金が多大にかかる。ましてや、ドワンゴの本社がある歌舞伎座タワー、つまり銀座の5km圏内というと、決して賃貸の相場も安くはない。

かつ、シェアハウスというのは面白いし、効率的でもある。

どこか銀座の5km圏内にシェアハウスでも立ち上げたいものだ。

しかし、シェアハウスを立ち上げるには、まず住人を集めて、物件を探さなければならない。シェアハウスに使える賃貸を探さなければならない上、広くないといけないので、初期費用だけでもそれなりにかかる。

難しい話だ。気長に考えておくとしよう。

2014-10-pre-Urbanaのレビュー: N4240-N4249

N4240: Improved insertion interface for unique-key maps (Revision 2)

std::mapとstd::unordered_mapにある要素の挿入あるいはemplaceするとき、すでに要素が存在する場合は、挿入やemplaceが行われない。しかし、以下のような問題がある。

std::map< int, std::unique_ptr<T> > m ;
m[0] = nullptr ;
auto ptr = std::make_unique<T>() ;
m.emplace( 0, std::move(ptr) ) ; // ムーブされるかどうかは未規定

bool b = ( ptr == nullptr ) ; // 結果は未規定

上記の例で、emplaceはすでにキーに対応する要素が存在するので、行われない。しかし、ライブラリの実装次第によっては、ムーブが行われる可能性がある。規格はこの挙動を規定していない。

N4240は、挙動の規定された新しいメンバーを追加しようという提案だ。

  • try_emplaceは、キーが存在する場合、何も挿入せず、ムーブも行わない。
  • insert_or_assignは、キーが存在しない場合は挿入し、存在する場合は代入する
std::map< int, std::unique_ptr<T> > m ;
m[0] = nullptr ;
auto ptr = std::make_unique<T>() ;

// 戻り地はpair<iterator, bool>
auto result = m.try_emplace( 0, std::move(ptr) ) ; // 何もしない。ムーブemされない

bool b = ( ptr == nullptr ) ; // false

result.first ; // キーに対応する要素へのイテレーター
result.second ; // false, 挿入が行われたかどうか。

N4241: A proposal to add shared_mutex (untimed) (Revision 3)

従来のshared_mutexはtimed lock要求を満たすため、shared_timed_mutexに解明されたことを受けて、timed lock要求を満たさないshared_mutexの提案。

N4242: Executors and Asynchronous Operations, Revision 1

スレッドプールなどの方法で細かいタスクを並列実行するライブラリの設計の提案。N3785とは違い、だいぶ軽い設計になっている。

N4243: Networking Library Proposal (Revision 2)

Boost.Asioを土台にしたネットワークライブラリの提案。

N4244: Resumable Lambdas: A language extension for generators and coroutines

resumable lambdaの提案。

N4245: C++ Standard Library Active Issues List
N4246: C++ Standard Library Defect Report List
N4247: C++ Standard Library Closed Issues List

標準ライブラリに持ち上がっている既知の問題、修正済みの問題、却下された問題の一覧。

N4248: Library Preconditions are a Language Feature

関数の実引数に対して、呼び出し側が満たすべき前提条件を記述できるコア言語の文法が必要であるとする提案。

まだ具体的な文法は定まっていないが、なぜ前提条件のチェック、制約が必要なのかや、既存の例について長文で考察している。

N4249: Networking Primitives: std::experimental::network::htonl Considered Harmful

N4023はhtonl, ntohl, htons, ntohsというライブラリを提案している。これはかの有名なバークレーソケットAPIと同じように機能する。すなわち、バイトオーダーの変換を行う。

問題は、既存の実装は、大方がプリプロセッサーマクロで提供されているということだ。C++の標準ライブラリに同名の関数を持ち込むと、既存のコードと衝突する。標準C++をサポートするための移行にかかる労力は非現実的なものとなる。

N4249は、標準ライブラリでhtonlのような名前を使うのをやめるべきであると提案している。

かなしい。

ドワンゴ広告

この記事はドワンゴ勤務中に書かれた。

最近、社内にポータルができつつある。

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

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

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

2014-12-03

2014-10-pre-Urbanaのレビュー: N4230-N4239

N4230: Nested namespace definition (revision 2)

namespace A::B::C {
    // ...
}

を、

namespace A {
    namespace B {
        namespace C {
            // ...
        }
    }
}

と同等にする提案。

これは個人的に入るべき小粒な機能だと思う。

N4231: Terms and definitions related to "threads"

規格における「スレッド」の意味するところに意見の不一致が見られるので、スレッドの意味を明確に定義する。また、スレッドより軽い実行媒体についても定義する。

N4232: Stackful Coroutines and Stackless Resumable Functions

コルーチンとレジューム可能関数には似通った部分があるから統一してはどうかという意見に対し、コルーチンとレジューム可能関数の違いを解説している文書。

N3985が提案しているコルーチンは、ライブラリである。スタックフルな実装であり、アドレス空間を多大に消費する。ライブラリなので今すぐに使うことができる。

N3858, N3977の提案しているレジューム可能関数は、コア言語機能である。スタックレスな実装であり、コルーチンのようにアドレス空間を浪費しない。コンパイラーによるサポートが必要である。

N4233: A Class for Status and Optional Value

N3533で提案されているConcurrent Queuesライブラリでは、値と状態を別々に返すように設計されている。

Value queue::value_pop();
queue_op_status queue::try_pop(Value&);
queue_op_status queue::nonblocking_pop(Value&);

この設計には、以下の制約がある。

  • value_popで状態が悪い場合、例外が投げられる
  • try_popとnonblocking_popを使う場合、Valueがデフォルト構築可能でなければならない

なにか状態と値を同時に返せるようなライブラリが欲しい。そう、例えば以下のような。


something<queue_op_status, Value> queue::value_pop();
something<queue_op_status, Value> queue::try_pop();
something<queue_op_status, Value> queue::nonblocking_pop();

設計上の要件としては、このsomethingは、必ず状態を有するが、値を有するかどうかは分からない。存在しない値にアクセスしようとすると例外を投げる。

これは提案中のoptionalやexpectedに似ている。ただし、optionalとexpectedは、値かエラーかのどちらか片方を格納するライブラリである。ここで欲しいのは、必ず状態を格納し、値を格納しているかどうかは分からないライブラリだ。

N4233は、このような要求を満たす、status_value< Status, Value >というライブラリを提案している。

N4234: 0-overhead-principle violations in exception handling - part 2

ゼロオーバーヘッドの原則(Zero Overhead Principal)とは、使わない機能のオーバーヘッドを支払うべきではないという原則である。ある機能があったとして、その機能を使わない場合、その機能をサポートするために必要なオーバーヘッドがもたらされてはならない。C++は伝統的に、この原則を強く意識してきた。Bjarne StroustrupがSimulaを使ってシミュレーターを書いたら、使いもしないGCのオーバーヘッドでプログラムの実行時間の80%が浪費されていたことは、あまりにも有名だ。

C++で、特にオーバーヘッドのやり玉に上げられるのは、例外である。例外のオーバーヘッドについては、N4049で考察されている。組み込みなどの資源制約の厳しい環境では、例外のオーバーヘッドは高く付きすぎる。

この論文、N4234では、もしユーザーが例外を使わずにSTLを用いた場合、規格と現在の実装は、現在の最適化技術であWhole Program AnalysisやLink Time Optimizationを用いて、例外によるゼロオーバーヘッドの原則(生成されたバイナリに例外サポートのためのコードが一切含まれないことを指す)を尊重できるのかどうかを考察している。

論文は、例外を使わないコンパイラーフラグや、例外を使わないSTL実装を使うことについては考察していない。

例外処理サポートのない特別なSTL実装の使用(gccの-fno-exceptionsフラグなど)は考察しない。例外処理は言語の一部であり、言語のサブセットを定義することは、過去にEmbedded C++があったように、好ましいことではない。

この論文では、以下のようなプログラムで実験を行った。

  • ::operator new(nothrow)を呼ぶアロケーター
  • main関数
  • noexceptではないvector::push_backの呼び出し
  • 純粋仮想関数が誤って呼ばれた場合に呼ばれる関数(__cxa_pure_virtual)を、ツールチェインの例外を使うデフォルト実装を上書きして定義する(ドキュメント化された方法である)

ターゲットプラットフォームはLinux x86-64(Ubuntu 14.04)で、GNUツールチェインが用いられた。Clangでも試したらしいが、同じ結果だったそうだ。

結果としては、生成されたバイナリには、例外サポートのためのシンボルが含まれていた。

理由はいくつかある。STL実装の内部で、_M_check_lenという関数が呼ばれ、これがlength_error例外を投げている。範囲外かどうかのチェックは規格で必須になっているため、これは規格準拠の実装である。operator new(nothrow)は、例外を使ってnew_handlerから投げられる例外を確認している。

_GLIBCXX_WEAK_DEFINITION void * 
operator new (std::size_t sz, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT 
{ 
  void *p; 
 
  /* malloc (0) is unpredictable; avoid it.  */ 
  if (sz == 0) 
    sz = 1; 
 
  while (__builtin_expect ((p = malloc (sz)) == 0, false)) 
    { 
      new_handler handler = std::get_new_handler (); 
      if (! handler) 
        return 0; 
      __try 
{ 
  handler (); 
} 
      __catch(const bad_alloc&) 
{ 
  return 0; 
} 
    } 
 
  return p; 
} 

なぜこんなコードでなければならないかというと、規格でoperator new(size)を呼び出すようになっているからだ。そして、operator new(size)は以下のように定義されている。

  • ループを実行する。ループの中で、まず要求されたストレージの確保を試みる。ストレージ確保の方法は実装依存である。
  • ストレージの確保が成功したならば、ストレージへのポインターを返す。ストレージの確保が成功しなかった場合で、現在のnew_handlerがnullポインターの場合、std::bad_allocをthrowする。
  • 現在のnew_handlerがnullポインター以外の場合、現在のnew_handlerを呼び出す。呼び出しが返ったならば、ループを続行する。
  • ループはストレージの確保が成功するか、new_handlerの呼び出しが返らなくなるまで、続けられる。

私が書いたC++11の文法と機能も参照。

operator newは、ストレージの確保に失敗した場合、new_handlerを呼び出してから、再びストレージ確保を試みる。new_handlerがループを打ち切ると判断したかどうかは、例外を使わなければ確認できない。

アロケーターでoperator new(nothrow_t)のかわりに、mallocを使ったプログラムの場合、例外サポートのためのシンボルを含まないバイナリの生成に成功したという。

このテスト結果を受けて、論文では、規格に以下のような改善案を提示している。

STLに対する改善案としては、

コンテナーにnoexcept版のメンバー関数を追加する。

引数の違いで追加する方法

void push_back (const value_type& val,  nothrow_t ) noexcept; 
void push_back (value_type&& val,  nothrow_t ) noexcept;  

あるいは別名で追加する。

範囲外チェックをoptionalにする。

C++に対する改善案としては、

noexcept修飾子で、ポインターを修飾することを可能にする。これによってオーバーロード解決でnoexcept版のメンバー関数が呼ばれる。

論文にサンプルコードはないが、以下のような感じだろうか。

struct X
{
    void f() ; // エラーを例外で通知
    bool f() noexcept ; // エラーを戻り値で通知
} ;

int main()
{
    X noexcept x ;
    x.f() ; // noexceptのオーバーロードが呼ばれる。
}

うーむ・・・

new_handlerに対しては、例外を投げないnew_nothrow_handlerを追加する改善案が示されている。s

標準ライブラリに例外を投げないstd::nothrow_allocatorを追加する案も示している。

N4235: Selecting from Parameter Packs

テンプレートパラメーターパックを扱う際に、N番目の型を取り出したいことがよくある。これは以下のように書くことができる。

template<int N, typename T0, typename ... Tr> struct nth_type_impl {
  using type = typename nth_type_impl<N-1, Tr...>::type;
};
  template<typename T0, typename ... Tr>
  struct nth_type_impl<0, T0, Tr...> {
    using type = T0;
  };
template<int N, typename ... Ts>
using nth_type = typename nth_type_impl<N, Ts...>::type;

template<typename ... Ts> struct App {
  nth_type<3, Ts...> n1;  // 4番目の要素.
}

これは動く。動くのだが、問題がある。これは再帰的なテンプレートのため、テンプレートのインスタンス化が大量に発生し、コンパイラー資源の浪費である。また、エラーメッセージもわかりにくい。

N4235では、パラメーターパックを扱うための便利な文法をいくつか提案している。

パラメーターパックからN番目の要素を取り出す文法

先ほどのAppは、以下のように簡潔に書くことができる。


template < typename ... Ts >
struct App
{
    Ts.[3] n1 ; // 4番目の要素
} ;

存在しない場合はエラーになる。

template < typename ... Types >
struct first
{
    using type = Types.[0] ;
} ;

using type = first<>::type ; // ill-formed

パックサブセット、パラメーターパックTsからsizeof...(Ns)だけ切り出す文法

Ts.<Ns...>

先頭からsizeof...(Ns)だけ要素を切り出したパラメーターパックになる。

N番目の要素だけ指定して切り出す文法

Ts.<1, 3, 5>

これは、2番目と4番目と6番目の要素のパラメーターパックになる。

Ts.<0, Ns..., 0>

これは、前後を最初の要素に挟まれたTs.<Ns...>になる。

整数シーケンスのパック展開を簡単に作れる文法 b ... < eも提案されている。

// {1,2,3,4,5,6,7,8,9}
int digits = { 0 ... < 10 } ;

これは、パックサブセットと組み合わせると強力になる。

// 最初の要素を除いたパラメーターパック
Ts.< 1 ... < sizeof...(Ts) >
// 最後の要素を除いたパラメーターパック
Ts.< 0 ... < sizeof...(Ts) - 1 >
// 要素を二度繰り返したパラメーターパック
Ts.< 0 ... < sizeof...(Ts), 0 ... sizeof...(Ts) >

また、この文法をプリプロセッサーでサポートするためにpp-numberにも変更を加える提案をしている。

面白い機能だ。文法にバイク小屋議論はあるだろうが、このような機能は欲しい。

N4236: A compile-time string library template with UDL operator templates

C++の文字列リテラルは、C言語から受け継いだ。C++では、std::basic_stringによって、文字列操作を高級にした。しかし、まだC++における文字列は扱いづらい。論文では、以下のようなサンプルコードで例示している。


// 結合
  //
  auto x1 = "Hello" + ", " + "World!"; // エラー!
  auto x2 = std::string("Hello") + ", " + "World!"; // 動くけど汚い。あと実行時コストがかかる
  auto x3 = "Hello" + std::string(", ") + "World!"; // エラー!
  auto x4 = "Hello" ", " "World!"; // 動くけど・・けど・・・

  auto conjunction = std::string(", ");
  auto x5 = "Hello" conjuction "World!"; // けど、これはエラーだろ。

  // ジェネリックプログラミング
  //
  template <typename T>
  typename T::size_type find(T t, typename T::value_type q)
  {
      return t.find(q);
  }

  auto s1 = std::string("One");
  auto s2 = "Two";

  find(s1, 'n'); // これはいい
  find(s2, 'w'); // エラー!
  find(std::string(s2), 'w'); // うごくけど、ちょっと待てよオイ

  // テンプレートメタプログラミング
  //
  template <typename T> struct metaprogram { /* ... */ };

  metaprogram<"Hello, World!"> m1; // エラー!
  metaprogram<std::string("Hello, World!")> m2; // そもそもなんじゃこりゃ
  metaprogram<decltype("Hello, World!")> m3; // そういう意味じゃない
  metaprogram<decltype(std::string("Hello, World!"))> m4; // これも違う
  metaprogram<boost::mpl::string<'Hell','o, W','orld', '!'>> m5; // やったぜ! ってなめとんのかー!
  metaprogram<_S("Hello, World!")> m6; // 詳細は気にするな

この論文は、文字列リテラルを使いやすくするために、新しいテンプレートライブラリstd::basic_string_literalと、ユーザー定義リテラルを提案している。これにより、上のコードは、以下のように書ける。

  // 結合
  //
  constexpr auto x1 = "Hello"S + ", "S + "World!"S; // 動く。実行時コストなし

  constexpr auto conjunction = ", "S;
  constexpr auto x5 = "Hello"S + conjuction + "World!"S; // 動く、実行時コストなし。

  // ジェネリックプログラミング
  //
  template <typename T>
  constexpr typename T::size_type find(T t, typename T::value_type q)
  {
      return t.find(q);
  }

  auto s1 = std::string("One");
  constexpr auto s2 = "Two"S;

  find(s1, 'n'); // 動く。
  find(s2, 'w'); // 動く。実行時コストなし

  // Template Metaprogramming
  //
  template <typename T> struct metaprogram { /* ... */ };

  metaprogram<decltype("Hello, World!"S)> m1; // 動く、実行時コストなし

このライブラリ、std::basic_string_literalのコンストラクターはprivateである。std::basic_string_literalは、ユーザー定義リテラルoperator "" Sによってのみ構築することができる。実行時オブジェクトを誤って作り出してしまうことを防ぐためである。std::basic_string_literalは、std::basic_stringにインターフェースを似せて設計されており、const std::basic_string相当のことができるようになっている。

N4237: Language Extensions for Vector loop level parallelism

Clik PlusやOpenMP 4.0を土台にしたベクトルループをコア言語機能として追加する提案。プリプロセッサーではなくキーワードを使う。

int main()
{
    int a[100] = { ... };
    int b[100] = { ... };
    int c[100] = { ... };

    for simd ( int i = 0 ; i < 100 ; ++i )
    {
        c[i] = a[i] + b[i] ;
    }

}

ベクトルループには制約が多い。たとえば、上記のコードを説明する。

ここで、iはInduction Variableである。繰り返し文の条件では、< ,>, <=, >=, ==, !=のどれかを使わなければならず、しかもそのオペランドの片方は、識別子でなければならない。識別子はInduction Variableをささなければならない。for文の3つめのオペランドは、インクリメントやデクリメント、あるいはそれに準ずるような式(+=とかa = b + cとか)しか書けない。ループの本体でInduction Variableを書き変える場合は、インクリメントやデクリメントの類しか使えない。

ベクトルループには、チャンクサイズを指定できる。

for simd safelen(5) ( int i = 0 ; i < 10 ; ++i )
{
    X ;
    Y ;
}

ここで、式Xが式Yに先行しなければならない場合、i == 6の時の式Xの実行の前に、i == 5の時の式Yの実行は先行している保証がある。

とにかく制約が強いし、その制約を厳格に文面化するために、文面はかなりわかりにくい。

N4238: An Abstract Model of Vector Parallelism

並列実行版の<algorithm>で、純粋なベクトル実行ポリシーを設計するための、ベクトル実行の抽象的なモデルを提示する。この論文は提案ではない。

N4239: Defaulted Comparison Using Reflection

デフォルトの比較演算子をコンパイラーが生成しようという提案があるが、そういうものは現在提案されているリフレクション機能を使ってライブラリでやればよいという提案。

リフレクション機能が十分に柔軟であれば、比較演算子にとどまらず、+=とかhashの自動生成まで行える。また、比較方法について意見の一致が見られないので、なおさら多様な挙動を柔軟に切り替えられるライブラリでやるべきことだとの主張だ。

ドワンゴ広告

この記事はドワンゴ勤務中に書かれた。

今日は、社内できのこの山派とたけのこの里派による宗教戦争が勃発したが、コーラタワー崩壊により終結したようだ。残念ながら、筆者は今回もコーラタワー崩壊を目にすることはかなわなかった。

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

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

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