4

そのテストコードでは:

#include <string>
#include <iostream>

using namespace std;

template <typename T> class Signal;

template <typename T, typename U>
class Signal<T (U)>
{
public:
  Signal<T (U)>(T (*ptr)(U))
  {
  }
};

void Print(string const& str)
{
  cout << str << endl;
}

int main(int argc, char *argv[])
{
  Signal<void (string const&)> sig = &Print;
  return 0;
}

なぜ私は書かなければならないのtemplate <typename T> class Signal;ですか?

なぜ指定する必要があるのですか?

4

2 に答える 2

3

あなたがしていることをする必要はありません、それは最も柔軟なアプローチです. 特殊化された 1 つのパラメーターのテンプレートは次のようになります。

  • 1 つの型でパラメータ化されたテンプレート...

    template <typename> struct Foo;
    
  • ...しかし、それは関数型に対してのみ定義されています:

    template <typename R>
    struct Foo<R()> { /* ... */ };
    
    template <typename R, typename A1>
    struct Foo<R(A1)> { /* ... */ };
    
    template <typename R, typename ...Args>
    struct Foo<R(Args...)> { /* ... */ };
    

別の方法は、関数のシグネチャをハードコードすることです。

  • 引数が 1 つの関数の関数ポインターを格納するクラス テンプレート:

    template <typename R, typename A>
    struct Bar
    {
        R (*fp)(A);
        Bar(R(*f)(A)) : fp(f) { }
        // ...
    };
    

ご覧のとおり、最初のアプローチは、好きな関数型に特化できるため、より一般ですFoo。対照的に、2 番目の例のダイレクト テンプレートは、関数シグネチャの詳細に複雑に結び付けられており、簡単に一般化することはできません。

于 2012-12-14T23:46:49.883 に答える
2

Signal任意の型を組み合わせてTフォームUに特殊化した を作成していますT(U)。これは特殊化としてまとめられています。パラメーターには 1 つの型しかないため、 1 つの型のみを取ることSignal<T(U)>を前方宣言しました。その宣言がなければ、これは不可能です。SignalT

簡単な例を次に示します。

template <typename T> struct A;

template <typename T, typename U> struct A<T(U)> {

};

int main() {

    A<void(int)> a;

}

タイプvoidとはそれぞれタイプとintにバインドされています。これは、クラスを特殊化するために の一次宣言で使用される型に結合されます。TUvoid(int)A

于 2012-12-14T23:34:00.660 に答える