読者です 読者をやめる 読者になる 読者になる

とくにあぶなくない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)

【BGM素材】evoke【島白】

島白さんの今年一つ目の曲がアップされました。

ループが自然ですね。バスドラが楽しげな哀愁系トランスです。

【BGM素材】evoke【島白】 - ニコニコ動画:GINZA

ニコニ・コモンズからMP3をダウンロードできます。

evoke - ニコニ・コモンズ

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

C++

再帰の欠点

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

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

再帰を消し去る例

再帰を消し去ることに挑戦してみましょう。 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 / 霧雨の森へ

Music

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

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

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

flow blue - ニコニ・コモンズ

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

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

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

Orpheus自動作曲による原曲

自動でdisposeを呼ぶusing

PowerShell

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.

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