bigsleepの日記

 | 

2012-02-12

variadic templateメモ

22:02

久しぶりにluaを使ってみようとしたところ、新しいバージョンになってた。

luabindも使おうとしたんだけれど、開発がどうもとまっているようで新しいバージョンのluaだと使えないみたい。

下のページに色々載っていたんだけれど、新しいバージョンに対応しているのはあまりないっぽい。

lua-users wiki: Binding Code To Lua

自分で簡単なラッパーを書いてみようかなとちょっと色々調べたりしてたんだけど、思ったより大変ではやくも挫折しそう。

古いバージョンのluaを使おうかな...。

あまり関係ないけどvariadic templateを久しぶりに使ったのでメモ。

index tupleという手法があるようで便利そうです。

c++ - How do I expand a tuple into variadic template function's arguments? - Stack Overflow

コンパイル時に配列を結合する - iorate's blog

(variadicな式)...と展開できると楽ですね。

ただこのように書ける場合とかけない場合があるようで例えば下のコードはコンパイルエラーになります。

#include <iostream>

template<typename T>
void display_impl(T a)
{
    std::cout << a << std::endl;
}

template<typename ... A>
void display(A ... a)
{
    display_impl(a)...; // コンパイルエラー
}

int main()
{
    display("hello", "world", 1, 2, 3);
}

これはなんでダメなのかなーと考えてたんですが、どうもdisplay_impl(a)...というとこをを展開するとvoid, void, void, void, voidとなるのでこれが文法的におかしいということのようです。

例えば下の場合にはコンパイルできました。

#include <iostream>

template<typename ... A>
void expand(A ... a){}

template<typename T>
char display_impl(T a)
{
    std::cout << a << std::endl;
    return 0;
}

template<typename ... A>
void display(A ... a)
{
    expand(display_impl(a)...);
}

int main()
{
    display("hello", "world", 1, 2, 3);
}

関数引数として渡すところや、初期化リストのところでは展開できるっぽいです。

戻り値まったく使わないし、なんか無駄な感じがしますが再帰で書くよりはかなり楽だと思います。

下のように書けるのかなと試してみたんですがこれはダメでした。

戻り値がvoidの関数には使う方法がないんだろうか。

#include <iostream>

template<typename ... A>
void expand(A ... a){}

char dummy(void){ return 0; }

template<typename T>
void display_impl(T a)
{
    std::cout << a << std::endl;
    return 0;
}

template<typename ... A>
void display(A ... a)
{
    expand(dummy(display_impl(a))...);
}

int main()
{
    display("hello", "world", 1, 2, 3);
}

追記

英語のWikipediaにほとんど同じようなことが書いてあった。

Variadic template - Wikipedia

 |