変数と同じ値の定数をテンプレート引数に渡す。

つまり以下のようになる。

template <int N>
void Function();

void Call(int n /* 0-2 */) {
    if (n == 0) {
        Function<0>();
    } else if (n == 1) {
        Function<1>();
    } else if (n == 2) {
        Function<2>();
    }
}

Callに渡された変数nに対応するFunctionを呼び出す。
予め渡される値毎に対応する静的なコードを書いておくしかない。
しかしながらこのコードは冗長であり避けたい。

そこで以下のようにすることでコードの重複を避けジェネリックに出来る。

template <int Max>
struct cross_switch {
    void operator()(int n) {
        static const int N = Max-1;
        if (N == n) {
            Function<N>();
        } else {
            cross_switch<N>()(n);
        }
    }
};
template<> struct cross_switch<0> {
    void operator()(int) {}
};

void Call(int n /* 0-2 */) {
    cross_switch<3>()(n);
}

また途中でboost::mpl::vector等の型リストを経由し、整数定数をindexに使用すれば
テンプレート引数に整数定数以外の型を渡すことも可能になる。

注意点:コードが膨張しやすい

関数の戻り値で悩むことってよくありますよね

関数の戻り値などで複数の状態を表したい場合、enumを使うのが正しい方法だと思います。
しかしながらついついint型を使用して-1だとか2だとかを直接書いてしまったりします。でもこれはなるべく避けたいところです。
そこでマルチキャラクリテラルが使えるんじゃないかと思い至りました。つまり戻り値を'ok'とか'fail'などシングルクォーテーションで括った4文字程度の値を使うわけです。これなら意味は明瞭ですし何も考えずにすみます。

unsigned func() {
    if () return 'fail';
    return 'ok';
}

int main() {
    unsigned ret = func();
    if (ret == 'ok') {
    } else if (ret == 'fail') {
    }
    return 0;
}

std::stringなどの普通の文字列型を使用すればパフォーマンスの劣化は避けられませんし、#include と書くのも手間です。


でもやっぱり一番良いのはenumですよね。

(char*) とか書いていませんか? sign_cast作ってみた

よく文字列やバッファを扱う関数でchar*とunsigned char*が変換できずに(char*)とか書いてませんか?
これはかなり危険な書き方なのでやめた方がいいです。C形式のキャストをやめてC++形式のキャストを使っても危ないです。
static_castだと変換できません。reinterpret_castを使用することになりますがこれもまた危ないです。char*型をやめてwchar_t*に切り替えたとしたら何の警告も出ずにコンパイルが通ってしまいます。
そこで符号だけを変換できるより安全なキャストを作りました。
safe sign-type cast · GitHub
これなら符号以外を変換しようとするとコンパイルエラーになってくれます。

#include "sign_cast.hpp"

unsigned char* s=0;
sign_cast<char*>(s); //ok
wchar_t* t=0;
sign_cast<char*>(t); //error

追記: 2012/04/20
const, volatileを付加する場合はコンパイルが通るようにしました。

C++0x(gcc 4.5.1 only)用のstatic ifライブラリを作ってみました。

C++にもstatic ifが欲しいと思い作ってみましたが、かなり苦戦しました。
やっぱり言語ネイティブでサポートして欲しいですね。C++0xの規格の範囲ではどうやっても無理そうで、gccの挙動に依存してます。
STATIC_IF library for C++ · GitHub
利点
static ifがあればコンパイル時プログラミングをよりわかり易く簡潔に記述できます。
定数を使った再帰的な関数等はコンパイル時に展開でき、その際に邪魔になる不要なインスタンス化を避けることができます。
従来はテンプレートの特殊化を使用して関数を分割し重複した関数定義を書く必要がありました。

使い方
関数テンプレート又はメンバ関数テンプレート内で使用する。
STATIC_IFではじめSTATIC_ENDIFで終わる。

#include "static_if.hpp"

template <int N>
void Repeat() {
    STATIC_IF(N>0) {
        std::cout << N << std::endl;
        Repeat<N-1>();
    }STATIC_ELSE{
        std::cout << "stop\n";
    }STATIC_ENDIF
}

Repeat<5>();

STATIC_IF, STATIC_ELSEIF, STATIC_ELSEを用意しました。STATIC_ELSEIFは何回でも使えます。
STATIC_IFはネスト可能です。
ラムダ式を使用しているのでスコープ外のローカル変数にもアクセス可能。
おまけの STATIC_BREAKIF を使うと一番内側のSTATICなブロックを抜けられます。

問題点
不要なインスタンス化を避けられている理由は不明でgccの挙動に依存していること。
関数テンプレート又はメンバ関数テンプレート内でしか使用できない。
スコープ内で return, continue, break, goto などが使用できない。

追記
C++14からgeneric lambdaが入ったのでマクロを使えば何とか規格の範囲でstatic_ifが実装できるようになりました。https://github.com/gununu/static_if
C++17から言語機能の if constexpr( ) が利用できるようになります。

マルチスレッドと落ちるウィンドウ

複数のスレッド内でウィンドウを作りメッセージループを回すということを何回も繰り返すと落ちる現象に遭遇しました。最初はスレッド関連か呼び出し規約など色々疑いましたが結局の原因はAT○Kでした。
デバッガの呼び出し履歴 WindowProc -> DefWindowProc -> user32 -> ntdll -> user32 -> atok
MS-IMEを使用すると落ちなくなりました。AT○Kェ・・・

散々時間を無駄にしましたがスレッド内でウィンドウを作成しても何も制限は無いという確証はMSDNより得られました。
http://support.microsoft.com/?scid=kb%3Ben-us%3B90975

std::mapのkeyをスライドしたい

何年も前にstd::mapに格納されているkey群を指定量だけ一気にずらしたいと思い、slidable_mapとでも呼べるデータ構造を考えました。つまり格納されているkeyが1,5,8だとしてそれぞれを+2だけずらし3,7,10としたいわけです。愚直に個々のkeyを修正すればコストはO(N)掛かります。しかしこの場合は全要素をずらしているのでmapとは別にスライド値を格納する変数を用意し併せて使うことでO(1)に出来ます。
しかしこの方法はmapの指定位置からのkeyだけをずらしたい場合には使えません。そこでslidable_mapの出番です。slidable_mapは赤黒木をベースにしてkeyの値を親のノードのkeyからの相対値で保持します。これにより全ノードのkeyを修正せずとも好きな範囲のkeyをO(logN)でずらすことが可能になります。方法は木の上からずらしたい位置に線を引きそれを挟んでジグザグにkeyを修正していきます。

mapのkeyは0,1,3,5,7,8,10の様に見えますが実際には親ノードとの相対値として格納しています。

8以降のkeyを+3ずらし0,1,3,5,7,11,13にする場合、8のkeyを+3ずらし+6とします。この親ノードの修正により7のkeyが+3の影響を受けるため-3ずらし-4とします。

デメリット
iteratorからkey本来の値を得るには木の一番上までたどる必要がありO(logN)のコストが掛かる。そのためstd::pairをインターフェイスに使うのは無理がある。

とっくの昔に誰か考えていそうではあります。
実装する際にはまず普通の赤黒木を作ってからのほうがいいかもしれません。一気に作ってデバッグでかなり苦労したので。

RGBからCMYKへ変換するには

RGBとCMYKカラーの変換には簡単な変換式はありませんし、完全に可逆の変換が出来るわけでもありません。また用途に応じて変換方法も違ってきます。
まずは適切なiccプロファイル(RGB,CMYK)を用意します。CMYKのプロファイルとしては日本で印刷するなら ( Japan Color 2011)などが有名でしょうか。あとは変換エンジンとなるカラーマネジメントモジュール(LittleCMSなど)を使いましょう。これはプログラマ向けのライブラリなので一般向けアプリケーションとしてはお絵かきソフトウェアのKritaが利用できます。


カラーマネジメントモジュールは具体的にどんな変換をしているかというと
まずRGBカラーを一旦L*a*b*カラーへ変換します。この変換には一般に正確な変換式があります。
しかしながらRGBカラーと言っても色空間はsRGBを始めとして色々ありますので各色空間のiccプロファイルのデータを用いて変換します。
つぎにL*a*b*からCMYKへ変換しますがこの変換には正確な変換式はありません。ではどうするかというとiccプロファイル内のルックアップテーブルを使用します。RGB系のプロファイルと比べてCMYK系のプロファイルのサイズが大きいのはこのルックアップテーブルがあるからです。

補足
実はL*a*bカラーといっても白色点の取り方によって値は異なってくるためD50、D65等が用いられます。この白色点の違いは相互に変換可能です。
XYZ色空間をL*a*b*色空間の代わりに用いることもできます。この2つは相互に変換可能です。
Lab色空間は広いため一般的にRGBカラーからLabへ正確にマッピングできますし、同じRGB色空間であればその逆も可能です。しかし全てのLabカラーをRGBカラーで表現することは変換はできません。これはCMYKとLabについても同じことが言えます。
RGBとCMYK、RGBとRGB、CMYKCMYKでは片方では表現できてももう片方では表現できない色域があったりします。