1. ホーム
  2. c++

[解決済み】テンプレートの引数として渡される関数

2022-04-18 17:27:54

質問

C++のテンプレート関数を引数として渡す際のルールを探しています。

これは、ここに例があるように、C++でサポートされています。

#include <iostream>

void add1(int &v)
{
  v+=1;
}

void add2(int &v)
{
  v+=2;
}

template <void (*T)(int &)>
void doOperation()
{
  int temp=0;
  T(temp);
  std::cout << "Result is " << temp << std::endl;
}

int main()
{
  doOperation<add1>();
  doOperation<add2>();
}

しかし、この技法を学ぶのは難しい。 ググってみると、"function as a template argument"と出てきます。 はあまり出てきません。また、古典的な C++テンプレート完全ガイド も意外と議論されていない(少なくとも私が検索した限りでは)。

私が抱いている疑問は、これが有効なC++なのか(それとも広くサポートされている拡張なのか)です。

また、このようなテンプレート呼び出しの際に、同じシグネチャを持つファンクタを明示的な関数と入れ替えて使用できるようにする方法はあるのでしょうか?

以下はその例です。 ではない は上記のプログラムでは、少なくとも ビジュアル C++ というのも、明らかに構文がおかしいからです。カスタムの比較演算を定義したい場合に std::sort アルゴリズムに関数ポインタやファンクタを渡すのと同じように、関数をファンクタに、またはその逆に切り替えられるといいんですけどね。

   struct add3 {
      void operator() (int &v) {v+=3;}
   };
...

    doOperation<add3>();

ウェブリンクやC++テンプレートブックのページへのポインタをお願いします。

どのように解決するのですか?

はい、有効です。

ファンクターでも使えるようにすることについては、通常、代わりに次のような解決策があります。

template <typename F>
void doOperation(F f)
{
  int temp=0;
  f(temp);
  std::cout << "Result is " << temp << std::endl;
}

のどちらかを呼び出すことができるようになりました。

doOperation(add2);
doOperation(add3());

ライブで見る

この場合の問題は、コンパイラがインラインで add2 というのは、コンパイラが知っているのは、関数ポインタ型の void (*)(int &) に渡されます。 doOperation . (ただし add3 はファンクタであるため,簡単にインライン化することができます.ここで,コンパイラは,型 add3 は関数に渡されます。つまり、呼び出すべき関数は add3::operator() であり、未知の関数ポインタではありません)。