とくにあぶなくないRiSKのブログ

危ないRiSKのブログだったかもしれない。本当はRiSKだけどググラビリティとか取得できるIDの都合でsscriskも使ったり。

GCC 5.1がリリースされました

新しいバージョンナンバリング方式になったので、いきなり 5.1 でリリースです。

変更点

  • Cのデフォルトモードが -std=gnu89 から -std=gnu11 に変更されました。
  • libstdc++ が新しい ABI を使うようになります。
  • C++0x 非標準の型特性(type traits)の has_trivial_default_constructor, has_trivial_copy_constructorhas_trivial_copy_assign は非推奨になり、次のバージョンでは削除されます。代わりに C++11 標準の is_trivially_default_constructible, is_trivially_copy_constructibleis_trivially_copy_assignable を使いましょう。

他にもリンク時最適化など、最適化周りが強化されるなどパワーアップしているようです。 C++11 がフルサポートされた他 C++14 対応もかなり進みました。

GCC 5 Release Series — Changes, New Features, and Fixes - GNU Project - Free Software Foundation (FSF)

テンプレートの再帰を無くそう

再帰の欠点

「テンプレートの再帰を無くす」…言うは易く行うは難しだとはいえ、再帰

  • 遅い
  • 再帰深度に限界がある
  • 恐ろしいエラーメッセージを出す

再帰を消し去る例

再帰を消し去ることに挑戦してみましょう。 T::value が全て true である時に true を返す all メタ関数を考えます。

再帰バージョン

普通に実装すると再帰を使って…

template<typename... T>
struct all;

template<>
struct all<>
{
    static constexpr bool value = true;
};

template<typename T, typename... Ts>
struct all<T, Ts...>
{
    static constexpr bool value = T::value && all<Ts...>::value;
};

使ってみます。ただし意図的にエラーにすると

[Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ

エラーメッセージは…

prog.cc:13:35: error: type 'int' cannot be used prior to '::' because it has no members
    static constexpr bool value = T::value && all<Ts...>::value;
                                 ^
prog.cc:13:47: note: in instantiation of template class 'all<int>' requested here
   static constexpr bool value = T::value && all<Ts...>::value;
                                             ^
prog.cc:13:47: note: in instantiation of template class 'all<FalseSample<2>, int>' requested here
   static constexpr bool value = T::value && all<Ts...>::value;
                                             ^
prog.cc:13:47: note: in instantiation of template class 'all<FalseSample<1>, FalseSample<2>, int>' requested here
   static constexpr bool value = T::value && all<Ts...>::value;
                                             ^
prog.cc:13:47: note: in instantiation of template class 'all<FalseSample<0>, FalseSample<1>, FalseSample<2>, int>' requested here
   static constexpr bool value = T::value && all<Ts...>::value;
                                             ^
prog.cc:13:47: note: in instantiation of template class 'all<TrueSample<3>, FalseSample<0>, FalseSample<1>, FalseSample<2>, int>' requested here
   static constexpr bool value = T::value && all<Ts...>::value;
                                             ^
prog.cc:13:47: note: in instantiation of template class 'all<TrueSample<2>, TrueSample<3>, FalseSample<0>, FalseSample<1>, FalseSample<2>, int>' requested here
    static constexpr bool value = T::value && all<Ts...>::value;
                                             ^
prog.cc:13:47: note: in instantiation of template class 'all<TrueSample<1>, TrueSample<2>, TrueSample<3>, FalseSample<0>, FalseSample<1>, FalseSample<2>, int>' requested here
   static constexpr bool value = T::value && all<Ts...>::value;
                                             ^
prog.cc:27:17: note: in instantiation of template class 'all<TrueSample<0>, TrueSample<1>, TrueSample<2>, TrueSample<3>, FalseSample<0>, FalseSample<1>, FalseSample<2>, int>' requested here
static_assert(! all<TrueSample<0>, TrueSample<1>, TrueSample<2>, TrueSample<3>,FalseSample<0>, FalseSample<1>, FalseSample<2>, int>::value, "Ooops");
               ^
1 error generated.

これはひどい。 (コンパイラの種類やバージョンによっては、これよりメッセージが改善されていることがあります。)

再帰無しバージョン

なんと再帰を使わないでも実装できます。

#include<type_traits>

template<bool...> struct boollist {};

template<typename...T>
struct all
{
    static constexpr bool value = std::is_same<boollist<T::value...>, boollist<(T::value, true)...>>::value;
};

使ってみます。

[Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ

今回のエラーメッセージは…

prog.cc:8:57: error: type 'int' cannot be used prior to '::' because it has no members
    static constexpr bool value = std::is_same<boollist<T::value...>, boollist<(T::value, true)...>>::value;
                                                       ^
prog.cc:22:17: note: in instantiation of template class 'all<TrueSample<0>, TrueSample<1>, TrueSample<2>, TrueSample<3>, FalseSample<0>, FalseSample<1>, FalseSample<2>, int>' requested here
static_assert(! all<TrueSample<0>, TrueSample<1>, TrueSample<2>, TrueSample<3>,FalseSample<0>, FalseSample<1>, FalseSample<2>, int>::value, "Ooops");
               ^
1 error generated.

短い。そして分かりやすいですね。

まとめ

テンプレートの再帰を極力使わないで実装してみよう!

参照

flow blue / 霧雨の森へ

久しぶりの島白さんの新曲。

BGM素材2曲追加:ほわいとあいらんど瓦版 - ブロマガ

「flow blue」と「霧雨の森へ」の2曲がアップされました。ニコニコ動画にはアップされていないようです。ニコニ・コモンズで視聴およびMP3のダウンロードできます。

flow blue - ニコニ・コモンズ

島白さんっぽい出だしからのサックスのメロ。さわやかさと疾走感の中に渋さがあってかっこいい。

霧雨の森へ - ニコニ・コモンズ

なんとなく西部。馬に乗ってぱっぱかぱっぱかって感じがすごくします。

Orpheus自動作曲による原曲

自動でdisposeを呼ぶusing

PowerShell 4.0 には IDisposable の Dispose を自動で呼ぶ仕組みが無いようです。無いならばどうにかしなければなりません。そこで、useという関数を作りました。

usingという識別子を使おうとするとエラーになるので、useという関数名にしています。ドキュメントのどこにも見当たらないのですが、usingがキーワードとみなされているようです。

function use([IDisposable]$disposable, [ScriptBlock]$block){
    try{
        &$block($disposable)
    }finally{
        if($disposable){ $disposable.Dispose() }
    }
}

以下のように使います。

use (New-Object IO.FileStream('in.txt', [IO.Filemode]::Open)){
    param($in)
    use (New-Object IO.FileStream('out.txt', [IO.FileMode]::Create)){
        param($out)
        $in.CopyTo($out)
    }
}

IDisposable のオブジェクトはスクリプトブロックの引数として渡されます。Disposeは勝手に呼ばれるので、スクリプトブロック内では好きなようにしてOK.

こういうのは基本的なパーツだと思うのですが、言語機能として無いのも不思議ですし、「言語に無いならどうにかしなきゃ」みたいな記事を日本語圏で見かけないのも不思議です。

basic_regexの概要を訳してみた

Twitter@kikairoyaさんに助けてもらいつつ。

N3337

28.8 Class template basic_regex [re.regex]

basic_regex クラステンプレート

1 For a char-like type charT, specializations of class template basic_regex represent regular expressions constructed from character sequences of charT characters. In the rest of 28.8, charT denotes a given charlike type. Storage for a regular expression is allocated and freed as necessary by the member functions of class basic_regex.

basic_regexクラステンプレートのcharT特殊化はcharT文字シーケンスから構築された正規表現を表す。 charTはcharのような型を示す。 正規表現のための記憶域はbasic_regexクラスのメンバ関数によって必要に応じて確保されたり解放される。

2 Objects of type specialization of basic_regex are responsible for converting the sequence of charT objects to an internal representation. It is not specified what form this representation takes, nor how it is accessed by algorithms that operate on regular expressions. [ Note: Implementations will typically declare some function templates as friends of basic_regex to achieve this —end note ]

特殊化したbasic_regexのオブジェクトはcharTシーケンスオブジェクトから内部表現に変換する責任がある。 それがどのような表現になるか、またどのように正規表現で動作するアルゴリズムによってアクセスされるかは未規定である。 (注:一般的な実装ではいくつかの関数テンプレートはbasic_regexのfriendとして宣言されるだろう。)

3 The functions described in this Clause report errors by throwing exceptions of type regex_error.

それら関数はregex_error型の例外を投げることによってエラーを報告する。

これでツッコミがないか、ツッコミがあり修正したならばcpprefjp - C++ Library Referenceの方に反映させたいと考えてます。