テンプレート引数に、テンプレート関数を指定する方法

[戻る]
Orange 2010/08/14(土) 02:26:09
お世話になります
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
だけで済むはず?
}

επιστημη [E-Mail] [HomePage] 2010/08/14(土) 06:43:17
>  c<a>();

aは型じゃありませんょ?

Orange 2010/08/14(土) 10:02:55
a<bool>やa<int>は、関数ポインタ型だから指定できて、
aだけだと、なんだか分からないから指定できない

つまりは、a<bool>やa<int>は、サイズがもとまるから指定できて、
aだけだと、サイズがもとまらないので指定できない

要するに、テンプレート引数には、型(サイズがもとまるもの)しか指定できない

ということでよろしいのでしょうか?

επιστημη [E-Mail] [HomePage] 2010/08/14(土) 10:22:33
> ということでよろしいのでしょうか?

ぜんぜんちがいます。

int i; があったとき、
a<int>() て書くでしょ?
a<i>() とは書かんでしょ?

でも iのサイズは自明でしょ?
「サイズが求まらないから」ではありません。
型ではないからです。

Orange 2010/08/14(土) 11:18:46
すみません型の認識がよく分かっていないようです

テンプレート関数は型ではないということなのでしょうか?

また、とんちんかんなこといっていたらすみません

Orange 2010/08/14(土) 11:55:54
> a<int>() て書くでしょ?
> a<i>() とは書かんでしょ?

intは型だからOK、iは変数だからNGってことでよろしいでしょうか?

επιστημη [E-Mail] [HomePage] 2010/08/14(土) 12:44:27
です。

質問に戻って、a は関数です。型じゃありません。

Orange 2010/08/14(土) 13:21:42
ありがとうございます
なるほどー、aは関数なので指定できない事は理解できました。

そうすると、また一つの疑問が出てきます

void d()
{
    ...
}

template< void (*f)() >
void e()
{
}

int main(void)
{
    e<d>();
}

この場合、dは関数だと思うのですが、テンプレート引数に指定できるのはなぜでしょうか?
dは型になるけど、aは型にはならないということなのでしょうか?

質問を重ねてすみません、よろしければお教えください

επιστημη [E-Mail] [HomePage] 2010/08/14(土) 15:01:07
template<class ...> や template<typename ...> の場合<>に入るのは型ですが、
template<int N> であれば <10> のように値を指定できます。

template< void (*f)() > に求められるtemplate引数は関数へのポインタ(つまり値)
となるわけです。

Orange 2010/08/14(土) 18:30:58
[[解決]]
なるほど、理解出来ました

関数ポインタなので、値の指定になり
dはポインタを返せるけど、aだとポインタを返せないのでテンプレート引数に指定できな
いということですね

  void (*f0)() = a;          // 関数の実体がない(実体を作りようがない)から
                               // ポインタを返せない
  void (*f1)() = a<bool>;    // 関数の実体ができるのでポインタを返せる
  void (*f2)() = d;          // 関数なのでポインタを返せる

私の、とんちんかんな質問に貴重な時間を割いていただき
まことにありがとうございました

Orange 2010/08/14(土) 21:00:15
蛇足ですが、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;
}

Orange 2010/08/15(日) 06:59:27
色々悩んだ結果

テンプレート関数だから指定できないということなので、
テンプレートクラスに変更することにしました
(本当は関数のままがいいんですけど…)

// 仕方なくテンプレートクラスに変更
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 2010/08/16(月) 10:18:43
> // この呼び出しって正しいのかな?
技術的には正しい。
一時オブジェクトを作って、呼び出しだけして、即時デストラクト。
この動作に意味があるのか?と問われて、意味があるかどうかは知らない。
(俺ならやらない)

この手の話は、単純に技術論だけに終始させてもいいんだけど
「なぜこういう呼び出しがしたいのか」あたりから始めると、
もっと根幹的な代案が出るかもしれない(し、出ないかもしれない)

Orange 2010/08/16(月) 16:03:04
επιστημηさん
tetrapodさん
回答ありがとうございました。


事の始まりは、
「型が違う所以外は同じ処理をする関数を次々に呼び出す処理」が必要になったので、
(本当に必要なの?という突っ込みはなしでw)
テンプレートを使って書こうと思ったのがきっかけでした。

最初、こんなのさっくり書けるだろうと思ったのですが、、、
なんか思ってるようにうまく書けない。

色々悩んだ結果、
「テンプレート引数に、テンプレート関数が指定できたらうまく書けるのでは?」
と思い、書き方が分からないので質問させていただいた次第です

結果、
「そんなもんは、テンプレート引数に指定できないぞ」
ということを教えていただき、それならばと思い、関数をクラスに、、、
と無理矢理な実装になりつつあります(汗
少々、b<a>の形にこだわりすぎなのかもしれません。


最終的に思うことは、「C++0xに、alias 引数を希望しますw」

PATIO 2010/08/16(月) 17:06:11
傍観していましたけれど、テンプレート関数aを作成する事に関しては
意義を感じますけれど、テンプレート関数bに関してはホントに必要なの?
と感じました。

テンプレート関数化すると言うのは、処理の汎用化にあると思うので
次々と呼び出す部分まで汎用化するメリットってあるの?
と言うのが本音ですね。
呼び出し部分は普通に記述すれば良いだけじゃないかと思っています。
多分、その方がソースを見た時に何をやっているのかはわかりやすいと
思うので。

もちろん、ソースを見る人が
関数aが何をする関数なのかを知っている前提になりますけれど。

PATIO 2010/08/16(月) 17:07:18
ごめん、突っ込みはなしでって書いてあった。

古いスレッドには追加発言できません。