4

次のような関数のセットを考えてみましょう

template< class Fun >
void A( const Fun& )
{
}

template< class Fun >
void B( const Fun& )
{
}

template< class Fun >
void C( const Fun& )
{
}

関数型を引数として取るように設計されています。次に、これは完全に問題ありません。

template< class T >
void Func( const T& )
{
}

A( Func< int > );
B( Func< int > );
C( Func< int > );

int今、私はtemaplate 引数の繰り返しを取り除きたかったので、これを試しました:

template< class T >
struct Helper
{
  template< template< class > class Fun >
  static void A( Fun< T >& f )
  {
    A( f );
  }

  template< template< class > class Fun >
  static void B( Fun< T >& f )
  {
    B( f );
  }

  ...
};

typedef Helper< int > IntHelper;
IntHelper::A( Func );  //error
IntHelper::B( Func );  //
IntHelper::C( Func );  //

ただし、これは gcc 4.5.1 ( 'error: no matching function for call to 'Helper<int>::A(<unresolved overloaded function type>)') および MSVC10 (cannot use function template 'void Func(const T &)' as a function argumentおよびcould not deduce template argument for 'overloaded function type' from 'overloaded function type') ではコンパイルに失敗します。

誰かが理由を正確に説明できますか?これを回避する方法はありますか?

編集OK 今はできない理由がわかりました。回避策を含む回答の場合:実際のコードにはFunc、たとえば100など、さまざまなsがたくさんありますが、A、B、Cなどの関数は約6つしかありません...

4

4 に答える 4

3

formtemplate<class> class Funは、宣言であろうとテンプレート テンプレート パラメータであろうと (あなたが持っているように)、クラステンプレート専用に設計されていますが、そうでFuncはありません。関数テンプレートです。これらは の形式template</*parameters*/> Ret foo(/*parameters*/)であり、テンプレート テンプレート パラメーターとしては許可されていません。

一般的に言えば、関数テンプレートはクラス テンプレートほど操作できません。

テンプレート パラメーターを渡さなくても済む状況が 1 つあります。

// Deduces that Func<int> is meant
void (*p)(int) = Func;

次に、 、およびに渡すpことができます。ABC

(同様に、関数がある場合void f(void(*p)(int));、フォームの呼び出しはf(Func)問題ありません。)

于 2012-07-25T14:32:43.340 に答える
3

Funcは関数テンプレートであるため、値として関数に渡すことはできません。

また、テンプレート テンプレート パラメーターはクラス テンプレート (関数テンプレートではない) である必要があるため、テンプレート テンプレート パラメーターとして渡すこともできません。

関数テンプレートをラップするテンプレート テンプレート パラメーターを渡すことができます (たとえば、静的メンバー関数からそのインスタンス化を返す)。

template<class T> struct FuncHelper {
    static void (*f())(const T &) { return &(Func<T>); }
};
template<typename T>
struct Helper
{
  template< template< class > class Fun >
  static void A()
  {
    A( Fun<T>::f() );
  }
};
Helper<int>::A<FuncHelper>();
于 2012-07-25T14:28:20.913 に答える
3

クラステンプレートをテンプレートパラメータとして使用することは可能ですが、例えば

template <typename> class Foo;

template <template <typename> class C> void doit() { /* ...*/ };

doit<Foo>();

関数テンプレートをテンプレート パラメーターとして使用することは (意味的に) 不可能です (「関数テンプレート ポインター」はありません)。通常の方法は、関数オブジェクトを使用することです。

template <typename T>
struct Func
{
  void operator()(T const &) const
  {
     /* ... */
  }
};


template <typename T>
struct helper
{
  template <template <typename> class F>
  static void A()
  {
    A(F<T>);
  }
  // etc
};

typedef helper<int> int_helper;

int_helper::A<Func>();
于 2012-07-25T14:42:21.953 に答える