お世話になります
WinXP(SP3) VC++2008 Express で開発しております
テンプレート引数に、テンプレート関数を指定する方法が分かりません
教えて頂けないでしょうか
template <class T>
void a()
{
...
}
template < void (*f1)(), void (*f2)(), void (*f3)() > // 型ごとに指定
void b()
{
f1();
f2();
f3();
}
template < ?? > // テンプレート関数の指定方法がわからない
void c() {
f<bool>();
f<int>();
f<float>();
}
int main(void)
{
b<a<bool>, a<int>, a<float>>(); // 型ごとに引数を指定するのは面倒
c<a>(); // テンプレート関数を引数に指定できれば、a
だけで済むはず?
}
> c<a>();
aは型じゃありませんょ?
a<bool>やa<int>は、関数ポインタ型だから指定できて、
aだけだと、なんだか分からないから指定できない
つまりは、a<bool>やa<int>は、サイズがもとまるから指定できて、
aだけだと、サイズがもとまらないので指定できない
要するに、テンプレート引数には、型(サイズがもとまるもの)しか指定できない
ということでよろしいのでしょうか?
> ということでよろしいのでしょうか?
ぜんぜんちがいます。
int i; があったとき、
a<int>() て書くでしょ?
a<i>() とは書かんでしょ?
でも iのサイズは自明でしょ?
「サイズが求まらないから」ではありません。
型ではないからです。
すみません型の認識がよく分かっていないようです
テンプレート関数は型ではないということなのでしょうか?
また、とんちんかんなこといっていたらすみません
> a<int>() て書くでしょ?
> a<i>() とは書かんでしょ?
intは型だからOK、iは変数だからNGってことでよろしいでしょうか?
です。
質問に戻って、a は関数です。型じゃありません。
ありがとうございます
なるほどー、aは関数なので指定できない事は理解できました。
そうすると、また一つの疑問が出てきます
void d()
{
...
}
template< void (*f)() >
void e()
{
}
int main(void)
{
e<d>();
}
この場合、dは関数だと思うのですが、テンプレート引数に指定できるのはなぜでしょうか?
dは型になるけど、aは型にはならないということなのでしょうか?
質問を重ねてすみません、よろしければお教えください
template<class ...> や template<typename ...> の場合<>に入るのは型ですが、
template<int N> であれば <10> のように値を指定できます。
template< void (*f)() > に求められるtemplate引数は関数へのポインタ(つまり値)
となるわけです。
なるほど、理解出来ました
関数ポインタなので、値の指定になり
dはポインタを返せるけど、aだとポインタを返せないのでテンプレート引数に指定できな
いということですね
void (*f0)() = a; // 関数の実体がない(実体を作りようがない)から
// ポインタを返せない
void (*f1)() = a<bool>; // 関数の実体ができるのでポインタを返せる
void (*f2)() = d; // 関数なのでポインタを返せる
私の、とんちんかんな質問に貴重な時間を割いていただき
まことにありがとうございました
蛇足ですが、D言語だと alias 引数を使ってあっさり書けそうですね
void a(T)()
{
printf(a() %d\n, T.sizeof);
}
void b( alias C )()
{
C!(bool)();
C!(int)();
C!(double)();
}
int main(char[][] args)
{
b!(a)();
return 0;
}
色々悩んだ結果
テンプレート関数だから指定できないということなので、
テンプレートクラスに変更することにしました
(本当は関数のままがいいんですけど…)
// 仕方なくテンプレートクラスに変更
template < class T >
class a
{
public:
void operator()()
{
printf(a() %d\n, sizeof(T));
}
};
template < template<class T> class C >
void b()
{
C<bool>()(); // この呼び出しって正しいのかな?
C<int>()();
C<double>()();
}
int main(void)
{
b<a>();
return 0;
}
> // この呼び出しって正しいのかな?
技術的には正しい。
一時オブジェクトを作って、呼び出しだけして、即時デストラクト。
この動作に意味があるのか?と問われて、意味があるかどうかは知らない。
(俺ならやらない)
この手の話は、単純に技術論だけに終始させてもいいんだけど
「なぜこういう呼び出しがしたいのか」あたりから始めると、
もっと根幹的な代案が出るかもしれない(し、出ないかもしれない)
επιστημηさん
tetrapodさん
回答ありがとうございました。
事の始まりは、
「型が違う所以外は同じ処理をする関数を次々に呼び出す処理」が必要になったので、
(本当に必要なの?という突っ込みはなしでw)
テンプレートを使って書こうと思ったのがきっかけでした。
最初、こんなのさっくり書けるだろうと思ったのですが、、、
なんか思ってるようにうまく書けない。
色々悩んだ結果、
「テンプレート引数に、テンプレート関数が指定できたらうまく書けるのでは?」
と思い、書き方が分からないので質問させていただいた次第です
結果、
「そんなもんは、テンプレート引数に指定できないぞ」
ということを教えていただき、それならばと思い、関数をクラスに、、、
と無理矢理な実装になりつつあります(汗
少々、b<a>の形にこだわりすぎなのかもしれません。
最終的に思うことは、「C++0xに、alias 引数を希望しますw」
傍観していましたけれど、テンプレート関数aを作成する事に関しては
意義を感じますけれど、テンプレート関数bに関してはホントに必要なの?
と感じました。
テンプレート関数化すると言うのは、処理の汎用化にあると思うので
次々と呼び出す部分まで汎用化するメリットってあるの?
と言うのが本音ですね。
呼び出し部分は普通に記述すれば良いだけじゃないかと思っています。
多分、その方がソースを見た時に何をやっているのかはわかりやすいと
思うので。
もちろん、ソースを見る人が
関数aが何をする関数なのかを知っている前提になりますけれど。