7

サブクラスで非テンプレート クラスのテンプレート メソッドを特殊化しようとしています。

// .h ファイル

class MyWriter {
public:
    template<typename T>
    void test(const T & val) {
        std::cout << val << "\n";
    }
};

// .cpp ファイル

class MyType {
public:
    MyType(int aa, double dd) : a(aa), d(dd) {}
    int a;
    double d;
};

class MyWriterExt : public MyWriter {
public:
    template<> void test(const MyType &val) {
        test(val.a);
        test(val.d);
    }
};

int main() {
    MyWriterExt w;
    w.test(10);
    w.test(9.999);
    w.test(MyType(15, 0.25));
 return 0;
}

しかし、私はエラーを受け取ります:

Error 1 **error C2912**: explicit specialization; 
'void MyWriterExt::test(const MyType &)' is not a specialization of a function 
    template \testtemplate.cpp 30

MyWriter クラスを拡張してユーザー定義クラスをサポートするにはどうすればよいですか?

4

2 に答える 2

7

特殊化は、サブクラスではなく、クラス本体の外でも同じクラスに対して行う必要があります。

class MyWriter {
public:
    template<typename T>
    void test(const T & val) {
        std::cout << val << "\n";
    }
};

template<>
void MyWriter::test<MyType>(const MyType & val) {
    test(val.a);
    test(val.d);
}

元のメンバー関数テンプレートを特殊化するためにサブクラスは必要ありません。

特殊化の代わりにオーバーロードも検討してください。

于 2010-11-14T09:43:42.720 に答える
5

コンパイルエラーを修正するには?

Error 1 **error C2912**: explicit specialization; 
 'void MyWriterExt::test(const MyType &)' is not a specialization of
     a function template \testtemplate.cpp 30

派生クラスでテンプレート化された関数の「特殊化」が必要な場合、解決策は(派生クラスで)次のとおりです。

  • テンプレート化された関数を MyType パラメータの通常の関数でオーバーロードします
  • テンプレート化された関数を現在のクラスに「インポート」します (オーバーロードによって隠されないようにします)

これにより、次のことが得られます。

class MyWriterExt : public MyWriter {
public:
/*
    template<> void test(const MyType &val) {
        test(val.a);
        test(val.d);
    }
*/
    using MyWriter::test ;
    void test(const MyType &val) {
        test(val.a);
        test(val.d);
    }

};

やりたいことを正しくコーディングする方法は?

MyWriter クラスを拡張してユーザー定義クラスをサポートするにはどうすればよいですか?

MyWriter を拡張可能な出力ストリームとして使用している場合、継承が解決策になるかどうかはわかりません。彼の答えについて vitaut がすでに答えたように; テンプレート化された関数をベース オブジェクト (および外部) に特化する必要があります。

やりたいことをより正確にコーディングする方法は?

MyWriter クラスを拡張してユーザー定義クラスをサポートするにはどうすればよいですか?

より良い解決策は、C++ ストリームの規則に従うこと、つまり、フレンドでもメンバーでもない関数を使用することです。あなたの場合、それは次のようになります:

class MyWriter {
public:
};

template<typename T>
MyWriter & operator << (MyWriter & writer, const T & val) {
    std::cout << val << "\n";
    return writer ;
}

継承を必要とせずに、誰でも出力関数を「特殊化」できます。

MyWriter & operator << (MyWriter & writer, const MyType & val) {
    writer << val.a << val.d ;
    return writer ;
}

あなたのメインで次のように書くことができます:

int main() {
    MyWriter w;
    w << 10 << 9.999 << MyType(15, 0.25);
 return 0;
}

これは、私見ですが、関数呼び出しの蓄積よりもかなり明確です (フォーマットを行っていない限り、C++ 出力ストリームは非常に使いやすいです)。

(もちろん、MyWriter は への単純なリダイレクト以上のことを行うと思いますstd::cout。そうでない場合、MyWriter は役に立ちません...)

于 2010-11-14T09:51:51.097 に答える