meryngii.neta

今日も新たな"ネタ"を求めて。

Template Aliases

C++11 Advent Calenderの26日目の記事です。
クリスマスまで残り365日と迫りましたね。C++11 Advent Forever.

さて、C++11で導入された機能の一つがTemplate Aliasesです。元々はTemplate Typedefなどとも呼ばれていました。他の主要な機能と比べて大して目立っていないですが、細かいポイントがいくつかあるような気がします。

Template Aliasesとは?

C言語でもtypedefを使えば型に好きな別名を付けることができます。C++のクラスも型ですからtypedefできます。ではテンプレートクラスはどうかというと、C++03まではそのままの名前で使うしか無かったのです。Template Aliasesならテンプレートに別名を与えることができます。そう、C++11ならね。

template <typename T>
using Vec = std::vector<T>; // Template Alias

Vec<int> v; // OK: std::vector<int> v; と同じ

あらかじめ引数を当てはめておくこともできます。

// 文字列をキーとする辞書(本当はC++11ならunordered_mapがオススメ)
template <typename T>
using Dictionary = std::map<std::string, T>;

Dictionary<double> dic;
// std::map<std::string, double> dic; と同じ

もう一つ例を挙げると、自作のアロケータを簡単に使えるというものがあります。

template <typename T>
class MyAllocator { /* ぼくの考えたさいきょうのアロケータ */ };

template <typename T>
using MyVector = std::vector<T, MyAllocator<T>>; // アロケータを埋め込む

MyVector<int> v; // 指定しなくても上のアロケータを使える

ここまでは割と簡単な例ですが、もっと複雑な型も自在に表現できます。なぜかというとメタプログラミングで作った型を取り出すことができるからです。

#include <type_traits> 

// constを取り除く
std::remove_const<const int>::type x1; // int x1;

template <typename T>
using remove_const = typename std::remove_const<T>::type; // typenameは必要

remove_const<const int> x2; // int x2;
typeが要らなくなるだけでも大分格好良くなります。

typedefを置き換える(普通の型のエイリアス

Template Aliasesはテンプレート引数+エイリアスという形で成り立っているので、エイリアスの部分だけ使用するとtypedefの代わりとして使えます。

typedef int intA_t;  // 古いシンタックス(C or C++03)
using intB_t = int;  // 新しいシンタックス(C++11)

これによって、C言語邪悪なシンタックス*1から幾分か解放されることになります。

typedef double (*func1A_t)(int);          // どれが新しい型名だろう?
using func1B_t = double (*)(int);         // 新しい型名が分かりやすい
using func1C_t = auto (*)(int) -> double; // 戻り値の後置も使ってみる

// intを引数に取って、doubleの配列への参照を返す関数へのポインタ
typedef double (&(*func2A_t)(int))[100];  // オエーッ
using func2B_t = double (&(*)(int))[100];
using func2C_t = auto (*)(int) -> double (&)[100]; // 若干読みやすい?

戻り値の後置については省略*2。配列への参照は昔書いたネタです。
alias declarationによって、typedefはCとの互換性以外の必要性が無くなりました。ナウでヤングなC++11プログラマはusingを使うべきなのです。数十年後typedefは絶滅する運命にあるのです。

変数のエイリアスは作れません

ところでよくある次のようなusing declaration

using std::string;

は、新しく導入されたエイリアスによって

using string = std::string;

とと同じになります。つまり、型のusing declarationはalias declarationの糖衣構文とも考えることができるらしいのです。
しかし、右辺に取れるのは型だけなので、

using std::cout; // OK
using Cout = std::cout; // エラー

となって変数では同様の考え方が成り立たないということになります。変数のエイリアスは十分なメリットがないとして導入されていません。

Template Aliasesの特殊化はできません

Template Aliasesは特殊化できません。例えば次のようなコードは不正です:

// 空想のコード
template <int> using int_exact;
template <> using int_exact<8> = signed char;
template <> using int_exact<16> = short;

int_exact<16> val; // short val;

しかしクラスの特殊化と組み合わせれば、

// コンパイルできる
template <int> struct int_exact_traits;
template <> struct int_exact_traits<8> { using type = signed char; };
template <> struct int_exact_traits<16> { using type = short; };

template <int N>
using int_exact = typename int_exact_traits<N>::type; // OK

int_exact<16> val; // short val; と同じ

このようなコードが書けるので問題ないわけです。Template Aliasesの特殊化が認められていない理由は、クラステンプレートの特殊化・エイリアスの特殊化の2つが入り乱れて混乱することを防ぐためだそうです。

Template Template Parametersに投入する

面白いことに、Template Aliasesはテンプレート実引数にできると標準で定められています。
c++ - Can I use template aliases as template template parameters? - Stack Overflow
これによってTemplate Template Parametersを使う際の問題点が改善されます。
Template Template Parameters - Faith and Brave - C++で遊ぼう

// (型ではなく)テンプレートクラスを引数に取る
template <template <typename> class Container>
class A { /* ... */ };

template <typename T>
using MyVector = std::vector<T, MyAllocator<T>>; // 先ほどの例

A<std::vector> a1; // エラー
A<MyVector> a2;    // OK!!!

そのままのstd::vectorはテンプレート引数が2つ必要ですから、Aは不正です。しかしTemplate Aliasesでラップしてあげれば、どんなテンプレートでも変形して与えることができるのです。

Template Template Parametersの応用というと真っ先にLokiのポリシーが思い浮かびますが、他はパッと思いつかないです。Boostのどこかで使われているかもしれません。

Template Aliasesを継承で置き換えられるか?

Template Aliasesが存在しなかったころにも代替策がいくつかありました。
http://msdn.microsoft.com/ja-jp/library/cc440199%28v=vs.71%29.aspx

  • マクロを使ってみる。(ダサい上に問題が多い)
  • テンプレートクラスで派生してみる。
  • traitsをそのまま利用する。仕方なく::typeを書く。Type Generatorとも言うらしい。

ここで派生に目を向けると、C++11ではコンストラクタを継承できる*3のでより簡単に実現できます。

template <typename T>
class MyVector
    : public std::vector<T>
{
    using Base = std::vector<T>; // ここでもAlias Declaration

public:
    using Base::Base; // コンストラクタの継承
};

いわゆるStrong Typedefと同じで、元の型とは異なる型になります。ただこれだけだと何か足りないかもしれないです。

まとめ

Template AliasesはGCC 4.7から導入されています。この記事に使用したコンパイラgcc version 4.7.0 20111217 (experimental)です。
Inheriting Constructorsはまだ実装されていないようです。もうそろそろ実装されると思うのですが…。

参照リンク

まず最初に読むならDr.StroustrupC++11 FAQが簡潔で分かりやすいです。他の項目も合わせてオススメです。
http://www2.research.att.com/~bs/C++0xFAQ.html#template-alias
詳しい解説は提案に書いてあります。
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1489.pdf
その他色々参考にしました。
GCC-4.7 に Alias declarations (Template aliases) が実装されていた - 野良C++erの雑記帳
Template Aliases すごい - C++でゲームプログラミング

次回予告

明日27日目のC++11 Advent CalenderはT.MURACHIさんです。乞うご期待!

*1:D&E 2.8.1も参照のこと。

*2:C++0x 新たな関数宣言構文 - Faith and Brave - C++で遊ぼうなど。引数に依存した戻り値を書きたいのが元々の動機ですが、スコープを解決できるなど他にも利点があります:http://www2.research.att.com/~bs/C++0xFAQ.html#suffix-return

*3:C++0x 継承コンストラクタ(Inheriting Constructors) - Faith and Brave - C++で遊ぼう

あなたもUbuntu Linuxユーザに(オススメソフト&設定)

パソコンに慣れている人ならLinuxの話を聞いたことくらいはあるだろうが、普段はWindowsを使っている人が大半だろう。Linuxも最近ではかなりユーザに優しくなっていて、日常作業の大半をこなせるようになってきている。

Linuxはサーバや組み込み用途で広く用いられているが、日常作業をこなすデスクトップOSとしてはあまり流行っていない。それでもLinuxで作業する理由はいくつかある。

APTなどのパッケージ管理が非常に便利
APTを使うと大抵のソフトはコマンド一行で、または数クリックでインストールできる。インストール済みのソフトも同様に丸ごとアップデートできる。Webサイトからインストーラを探してダウンロードするという工程が必要ないのだ。特にパッケージ管理の恩恵が感じられるのはLaTeXLAMPなどで複数のソフトを混ぜて使う状況で、依存関係がきちんと管理されているおかげで面倒な設定が必要ない。
ほとんどウィルスがいない
Linuxのセキュリティは堅牢で、Windowsと違ってウィルス対策ソフトの必要性が薄いと言われている。これにはオープンソースであること、パッケージが最新に保たれていること、そしてシェアが低いこと、などいくつか理由がある*1。もちろんLinuxのウィルスが存在しないわけではないので、一応ウィルス対策ソフトも用意されている。
CUI操作が強力
コマンド操作ができるだけでハッカー気分というのは半分冗談だが、大量のファイルをバッチ処理する場合などにLinuxの強力なシェルが生かせる。また、情報系の勉強をしている人なら、自然とUnix系のコマンドを覚えていけるので非常に有意義だと思う。
軽い(?)、安定している
他のOSより何となく軽いような気がする。もっとも、UbuntuLinuxとしてはかなり重量級なのだが…。
基本的にタダ
WindowsだってPCを買うと一緒にバンドルされているから、普通のユーザにとってみればタダのような感覚だ。Linuxがタダで使えることの利点は複数台PCを持っているときに現れる。何らかの事情で古いPCが余ったとき、新たにWindowsを買い足すことなく最新の環境を使うことができる。

私は最近メインPCをWindowsからUbuntu Linuxに移行した。UbuntuはデスクトップLinuxの中でも定評があって、GUIの使いやすさ・ドライバの対応度などが優れている。初心者の方にはまずUbuntuが妥当だと思う。

一方で、一般ユーザがLinuxに乗り換えるには多くの障壁が立ちはだかっている。

  • 今まで使用していたソフトが動かない、さらには代替品がない
  • 周辺機器にドライバが対応していないことがある

そのため、Windows専用の商用ソフトを多く使用している人、PCゲームが好きな人、特殊な周辺機器をたくさん持っている人などなどにはLinuxは合わないと思う。そういう人にはVMware上での限定的な試用をお薦めしたい。それでもし気に入ったらネイティブにインストールしてみるのもいいと思う。

私はWindowsでもオープンソースソフトしか使っていなかったのでUbuntuへの移行は割とスムーズだった。必要に応じてまたWindowsも使うかもしれないが、Linuxを幅広く使っていくことに変わりはないと思う。

Ubuntuのインストール

現在最新のバージョンはUbuntu 11.10となっている。

Ubuntuをインストールするには、Ubuntu Japanese TeamのサイトからイメージをダウンロードしてCDに書き込んで、CDからPCを起動する。場合によってはBIOSの設定を書き換える必要があるかもしれない。CDドライブやCD-Rが無いならUnetBootinでUSBドライブに書き込んでもいい。

インストール前にHDDのパーティションLinux用に切り分けておく必要がある。Windows標準の「ディスクの管理」で限界がある場合もEASEUS Partition Masterなどを使えば自由に操作できる。

基本的にインストール中は説明に従って操作していけば正常にインストールできる。ただ操作ミスでHDDのデータが消えてしまうことがあるかもしれないので、心配ならバックアップは取っておく。

Windowsが入っている場合はデュアルブートを選択する場合が多いと思う。少し手間がかかってもいいなら、私としてはWindowsブートローダからブートする方法をお薦めしたい。この方法なら最初の設定を間違えなければWindowsが起動しなくなることが無い。
taka8aru: WindowsのブートローダーでLinuxとデュアルブートする方法 - Ubuntu 11.04/12.04/12.10, Grub2の場合
上記のサイトではGRUB4DOSでチェインロードする方法を紹介している。Vista/7だと直接GRUB2をロードできる(?)らしく次のサイトの方法でもいい。
Windows 7のブートローダでLinuxのUbuntuとデュアルブートする方法 - MiuxMiu

各種設定 & おすすめソフトウェア

以下の解説はこちらのサイトも参考にした。

http://www.k5.dion.ne.jp/~r-f/sicklylife/memo/ubuntu1110/setting_and_install.html

端末の操作

「端末」(Ctrl+Alt+T)を起動すると、コマンドでの操作ができる。できることなら早いうちからコマンドでの操作に慣れると楽。

必要なソフトウェアはapt-getでインストールできる。慣れないうちは「Ubuntuソフトウェアセンター」を使うのもあり。*2

sudo apt-get update
パッケージリストを最新にする
sudo apt-get upgrade
インストール済みのパッケージを更新
sudo apt-get install 〜
〜をインストール

Ubuntuをインストールしたばかりならまずアップデートする。

sudo apt-get update
sudo apt-get upgrade
フォルダの英語表記

ターミナルを使う場合にホームフォルダの「音楽」といった日本語名はタイプしにくい。次のコマンドを打つと英語表記に戻せる。

LANG=C xdg-user-dirs-gtk-update

出てきたダイアログで"Don't ask me this again"にチェックを入れ"Update Names"をクリックすれば変更される。

Unityの設定

UbuntuGUIはUnityというものが採用されている。Unityの動作を変更したい時は、UnityのベースとなっているCompizを設定する必要がある。

sudo apt-get install compizconfig-settings-manager

左のランチャが毎回消えるのが嫌なので、消えないようにする。

  1. 「CompizConfig 設定マネージャ」 を起動(Superを押して"compiz"と入力)
  2. Ubuntu Unity Plugin を選択
  3. Behaviour タブの Hide Launcher を Never に

再度ログインすれば設定が反映される。

Webブラウザ : Firefox

Firefoxは標準でインストールされている。プラグインなどもWindows版と同じものが使え、自由にカスタマイズできる。

テキストエディタ : gedit

geditは標準でインストール済みのテキストエディタで、Windowsユーザにも使いやすい。

  • バックアップが自動で生成されるようになっているのでこれを解除する。
    • テキストエディター」(Super + "gedit")を起動して 編集 > 設定 > エディター > 保存する前にバックアップを生成する のチェックを外す。
Vim : GVim

LinuxテキストエディタにはViとEmacsが有名で、どちらにも熱狂的なファンがたくさんいる。
私が試用した限りではViの方が使いやすいと思ったので、GVimをインストールする。*3

sudo apt-get install vim-gnome

Vimのカスタマイズについてはここでは解説し切れない。私はVim初心者なので、現在~/.vimrcにわずかだけ追加している。

set tabstop=4
set softtabstop=4
set shiftwidth=4

set autoindent
set expandtab

set wildmode=list,full
日本語入力 : Mozc

MozcはGoogle日本語入力オープンソース版で、Linuxでも使える。デフォルトのAnthyよりずっと使いやすいのでオススメ。

sudo apt-get install ibus-mozc

右上のバーにIMEのアイコンから、インプットメソッド > インプットメソッドの選択 > 日本語 > Mozcと選択して「追加」をクリックし、Mozcをクリックして「上へ」。

動画プレイヤー : VLC Media Player

VLCは様々な形式の動画をコーデック無しに再生できるプレイヤー。非常に便利なのでオススメ。

sudo apt-get install vlc
画像編集ソフト : Inkscape , GIMP

InkscapeIllustratorのようにベクタ画像を編集する場合に、GIMPPhotoshopのように写真などラスタ画像を編集する場合に使う。どちらも有名で使いやすい。

sudo apt-get install inkscape gimp
MP3タグ編集 : EasyTag

MP3のタグをまとめて編集できる。WindowsでいうとMP3Tagのような感じ。

sudo apt-get install easytag

尚、日本語版だとCDDBで検索する際に強制終了するバグがあるようなので、必要に応じて英語にして起動する。

LANG=C easytag
追加アーカイバ

よく使われる書庫形式のアーカイバをインストールしておく。

sudo apt-get install lha-sjis p7zip-full rar unrar
クラウドストレージ : Ubuntu One , Dropbox , ...

クラウドストレージとは、オンラインにファイルをアップロードし、複数のコンピュータから共有できるサービスのこと。代表的なサービスとしてDropboxやSugarSyncなどがある。

UbuntuにはUbuntu Oneというクラウドストレージがあらかじめインストールされていて、起動して登録すると5GBの容量を無料で使うことができる。WindowsiPhoneAndroidなど他OS版も存在する。

DropboxにもLinux版があり.debパッケージになっている。容量は2GB。下のサイトから「Ubuntu (x86 .deb)」をダウンロードしてインストールする。

https://www.dropbox.com/downloading?os=lnx

SugarSyncは現在Linuxに対応していない。*4

Wine

Windows用のソフトをネイティブで動かせる。

sudo add-apt-repository ppa:ubuntu-wine/ppa
sudo apt-get update
sudo apt-get install wine1.3
winecfg
Wine で Office 2007

Wine上でOffice 2007をかなりの再現度で実行できる。Microsoft Officeのシェアは非常に高く、LibreOfficeは互換性が今ひとつなので、どうしても必要になってくる。

Officeのインストールは色々なサイトで解説されているが、単にOffice 2007を入れるだけなら細かい設定は必要ない。winetricksなどで色々いじってインストールした場合は、Wineサポート対象外であるとはっきりWine公式サイトに書いてある。

インストールする前にWindowsからフォントをコピーしておく。*5"C:\Windows\Fonts"から"~/.wine/drive_c/windows/Fonts"にいくつかコピーする。

  • msmincho.ttc , msgothic.ttc
  • tahoma.ttc, tahoma.ttf : インストール時の画面を読むために必要
  • wingding.ttf : Wordの箇条書きの記号などを表示するために必要

インストールディスクをDVDドライブに入れ、「setup.exe」を右クリックして「Wine Windows Program Loader」で起動すればインストールできる。注意点として、必ず本物のDVDドライブから起動しなければいけないらしい。Ubuntuの書庫マネージャーやアーカイブマウンタは、今のところISOイメージのUDFを読み込めないようだ。

インストール後に起動する前にwinecfgで設定する必要がある。

  • ライブラリ > ライブラリの新規オーバーライド に riched20 と打ち込んで、「追加」をクリック。下に出てくるriched20を選択し「編集」から「Native (Windows)」に変更する。

Wine上での日本語IMEの動作は不安定なので、~/.wine/user.regに次の記述を追加する。変換途中の文字列が常に左下に表示されるので見づらいが、ここは表示されないよりはマシだと思うしかない。

[Software\\Wine\\X11 Driver]
"InputStyle"="root"
Wineのアンインストール

Wine上でのWindowsアプリのインストールは失敗することが多いので、Wineを丸ごと削除する方法を覚えておいたほうがいい。
FAQ ja - The Official Wine Wiki

まずパッケージを削除する。*6

sudo apt-get --purge autoremove wine

これだけだとWineの設定ファイルは削除されないので、以下のコマンドを実行する。

rm -rf ~/.wine
sudo rm -f ~/.config/menus/applications-merged/wine*
rm -rf ~/.local/share/applications/wine
rm -f ~/.local/share/desktop-directories/wine*
rm -f ~/.local/share/icons/????_*.{xpm,png}
rm -f ~/.local/share/icons/*-x-wine-*.{xpm,png}

ここまでやっても関連付けが消えないので、適当に自分で削除する。

rm -f ~/.local/share/applications/wine*
gvim ~/.local/share/applications/mimeinfo.cache

mimeinfo.cacheからwineが含まれている行を削除する。

さらにWineのリポジトリを削除する場合は、

sudo add-apt-repository -r ppa:ubuntu-wine/ppa

必要に応じて

2chブラウザ : JD

2chブラウザは必要な人だけ。

JDを入れる前に、AAがずれないよう「小夏フォント」「モナーフォント」(MS P ゴシックなどの代わり)などを入れておいた方がいい。

sudo apt-get install ttf-konatu jd
  • 初回起動時は「3ペイン表示」を選択
  • URLバーにabout:configと入れると詳細な設定ができる(~/.jd/jd.confを編集するのと同じ)

このままだとビットマップフォントで表示されて見づらいので設定する。

Tips - JD for Linux Wiki - JD for Linux - SourceForge.JP

まず~/.font.confに次の内容を入力する。


    
        Konatu
    
    
        false
    
    
        false
    

端末で次のコマンドを実行する。

fc-cache -fv
Loqui

LoquiはLimeChatライクなIRCクライアント。

sudo apt-get install loqui

理工系向け

大学のレポートや論文などに役立つソフトを中心に。

組版 : LaTeX

LaTeXは書籍や論文を書くのに一般的なツール。

sudo apt-get install texlive texlive-latex-extra ptex-bin okumura-clsfiles
sudo apt-get install dvipdfmx dvipsk-ja jmpost jbibtex-bin mendexk
sudo apt-get install adobereader-jpn cmap-adobe-japan1

あるいは一行で

sudo apt-get install texlive texlive-latex-extra ptex-bin okumura-clsfiles dvipdfmx dvipsk-ja jmpost jbibtex-bin mendexk adobereader-jpn cmap-adobe-japan1

例えば日本語のPDFを生成する場合は次のように端末に入力する。

platex test.tex && dvipdfmx test.dvi

ちなみにAdobe Readerのメニュー項目が表示されないバグがあるらしく、回避策は以下を参照のこと。
http://linux.ikoinoba.net/index.php?UID=1307549419

数式処理 : Maxima

Maximaはフリーの数式処理システムで、Mathematicaなどと同じようなことができる。複雑な数式を簡略化したり、近似計算せずに微積分・微分方程式・行列などの問題を解いたりできる。

sudo apt-get install wxmaxima
C++ : g++

もちろんC++はインストールするよね!

sudo apt-get install build-essential
Haskell : GHC

Haskellは有名な純粋関数型言語で、GHCはそのデファクトスタンダードな処理系。

sudo apt-get install ghc
プリント基板 : Eagle

Eagleをインストールしておくと回路図やパターン図を見ることができる。

sudo apt-get install eagle

その他面白いツール

Ubuntu Customization Kit

UbuntuのライブCDをカスタマイズできる。

sudo apt-get install uck

メモ

  • iTunesはまともに使ったことがないので詳しくは分からないが、Bansheeがうまく対応しているかもしれない。
  • Evernoteについては良案がない。ChromiumからWebで操作するのが堅実かもしれない。ちなみにNixNote(旧称NeverNote)は非常に重いのでオススメできないし、WindowsEvernoteをWineで動かすのはさらに重い。
  • 現在Ubuntu 11.10の書庫マネージャーにバグがあるようで、ISOを解凍するとファイル名の末尾に「;1」が付いてしまう。
    • ファイル名だけなら「find . | rename "s/;1//"」で直せるが、それでも正常に展開できるとは限らない。

*1:http://unnnunnnet.blog47.fc2.com/blog-entry-64.html

*2:Synapticはデフォルトでインストールされなくなった。

*3:Emacsの「徹底的にカスタマイズする」という思想より、Viの「最低限あればいい」という思想の方が自分には合っているような気はする。もっとも、Vimはカスタマイズするのが普通らしいが…。

*4:Windows用のクライアントをWineで動かす猛者もいるらしい。

*5:ライセンス的にあやしいので自己責任で。

*6:またインストールするならパッケージは削除しなくてもいいのかもしれない。

Suffix Arrayの低速な生成

ふと思い立ってSuffix Arrayを適当に実装することにした。
wikipedia:接尾辞配列
本当はSuffix Array専用の高速な生成方法(O(n log n))があるのだが、今回は適当な実装なのでソートアルゴリズムを使う(O(n^2 log n))。

#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
#include <algorithm>

template <typename Iterator1, typename Iterator2>
bool string_less(Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2)
{
	while (true)
	{
		if (first2 == last2) return false;   // ? < '\0' == 0
		if (first1 == last1) return true;    // '\0' < ?(>'\0') == 1 
		if (*first1 != *first2) return *first1 < *first2;
		++first1;
		++first2;
	}
}

int main()
{
	std::string str("abracadabra");
	
	std::vector<unsigned long> ar;
	for (unsigned long i = 0; i < str.length(); i++)
		ar.push_back(i);
	
	std::sort(ar.begin(), ar.end(),
		[&](unsigned long a, unsigned long b)->bool
			{ return string_less(str.begin()+a, str.end(), str.begin()+b, str.end()); }
	);
	
	for (auto i : ar)
	{
		std::cout << std::setw(3) << i << " ";
		
		for (auto itr = str.begin()+i; itr != str.end(); itr++)
			std::cout << *itr;
		
		std::cout << std::endl;
	}
}

せっかくなのでC++11の機能を生かそうと思ったのだが、今ひとつ活用出来ていない。気が向いたら高速なものも実装してみようと思う。

GCC 4.6.1をUbuntu 11.04でmake

C++0xの機能を試すためにGCC 4.6が欲しいのだが、UbuntuにはGCC 4.5のパッケージしか用意されていない。こういう時はソースを落としてきてコンパイルすればよい。
GCCコンパイルには数学関連のライブラリが必要で、それらを先にコンパイルしてインストールしてもよい。しかしmake installするとアンインストールできない事態に陥る。基本的にAPTで全部管理させたいので調べたところ、lib*-devをインストールすればよいことが分かった。

sudo apt-get install libgmp3-dev libmpfr-dev libmpc-dev

で、あとはhttp://gcc.gnu.org/mirrors.htmlからソースを落としてきてmakeするだけと思いきや、

tar xvf gcc-4.6.1.tar.bz2
cd gcc-4.6.1
./configure
make

"asm/errno.h"が見つからないとかいうエラーが出る。最近のUbuntuで生じる問題らしい。
http://am112705.blog.so-net.ne.jp/2011-05-01
とりあえずシンボリックリンクを張る。

sudo ln -s /usr/include/asm-generic /usr/include/asm
make

make成功。
ここでmake installするとアンインストールできなくなる。そこで自動的にパッケージを生成してくれるCheckInstallを試したのだが、途中でエラーを吐いて上手くいかない。代わりに試したpacoは使いにくかったので、結局普通にmake installすることになった。

sudo make install
gcc -v

GCC 4.6.1となれば終了。すぐ終わるかと思ったが意外と手間取った。

再始動

久々にブログを再開します。
私がC++からしばらく遠ざかっていた間にC++0xC++11として国際標準になりました。関係者の皆さんの努力に感謝です。
これからもC++11の備忘録を続けていきますが、興味が湧いたらソフトウェアを軸としていろんなコトに挑戦していくつもりです。
尚最近はTwitterでも活動し始めました。まとまりの無い話はツイートで書くことにしてるので、そちらもよろしくです。

boost::tieのネスト

アキラさんの記事を読んでboost::tieのことを思い出し、もしかしてこいつはネストできるのかと気になったので調べてみた。

#include <boost/tuple/tuple.hpp>

int main()
{
	using namespace boost;
	
	int i; double d; const char* s;
	tie(tie(i, d), s) = make_tuple(make_tuple(123, 123.4), "abc");
}

残念ながらこのコードはエラーになった。どうやらtieは引数に左辺値を要求しているらしく、内側のtieが返した右辺値を外側のtieが受け取ってエラーになるようだ。

空メンバの最適化をVariadic Templatesで

The "Empty Member" C++ Optimization
これにVariadic Templatesを使ってみようと思いついた。

template <typename Member, typename... Bases>
struct BaseOpt
    : Bases...
{
    Member m;
    
    template <typename... Arg>
    BaseOpt(Arg&&... arg) : m(std::forward<Arg>(arg)...) { }
};

class X { static void foo() { } };
class Y { static int bar(int x) { return x; } };

struct Z
{
    Z() : m(123) { }
    BaseOpt<int, X, Y> m;
};

ベースクラスにコンストラクタ引数を与えるのは難しそうだ。そこまでするなら手書きした方が早いかもしれない。