0

クラス定義/宣言内でパブリック メンバー関数テンプレートを特殊化しようとすると、次のようになります。

#include <iostream>

class surfaceMesh 
{
    public:
        // Uncomment for Version 0 and 1
        class AREA_AVERAGE {};
        class ANGLE_AVERAGE {};  

        template<class Average>
        void vertexNormals() {}

        // Uncomment: Version 0
        //template<>
        //void vertexNormals<AREA_AVERAGE> ()
        //{
            //std::cout << "AREA_AVERAGE" << std::endl;
        //}

        //template<>
        //void vertexNormals<ANGLE_AVERAGE> ()
        //{
            //std::cout << "ANGLE_AVERAGE" << std::endl;
        //}


};

// Uncommend for version 1 
template<>
void surfaceMesh::vertexNormals<surfaceMesh::AREA_AVERAGE> ()
{
    std::cout << "AREA_AVERAGE" << std::endl;
};

template<>
void surfaceMesh::vertexNormals<surfaceMesh::ANGLE_AVERAGE> ()
{
    std::cout << "ANGLE_AVERAGE" << std::endl;
};


int main()
{
    surfaceMesh m;

    m.vertexNormals<surfaceMesh::AREA_AVERAGE>();
    m.vertexNormals<surfaceMesh::ANGLE_AVERAGE>();

    return 0;
}

バージョン 0 の場合、エラーは次のとおりです。

main.cpp:19: error: template-id ‘vertexNormals<mesh::AREA_AVERAGE>’ in declaration of primary template
main.cpp:24: error: explicit specialization in non-namespace scope ‘class mesh’
main.cpp:25: error: template-id ‘vertexNormals<mesh::ANGLE_AVERAGE>’ in declaration of primary template
main.cpp:25: error: ‘void mesh::vertexNormals()’ cannot be overloaded
main.cpp:19: error: with ‘void mesh::vertexNormals()’

バージョン 1 はコンパイルして実行します。もちろん、通常はクラスの宣言と定義を分けていますが、なぜそうなるのか知りたいです。

また、これはインターフェイスを特殊化する良い方法ですか? もう 1 つのオプションは、関数 vertexNormals をオーバーロードして、AREA_AVERAGE または ANGLE_AVERAGE のオブジェクトを取得することですが、これは、使用する関数の種類を示す単なる型であり、インスタンス化されることは想定されていないため、テンプレートを使用すると「感じる」正しい選択のように。

4

1 に答える 1

4

クラス内でメンバー関数テンプレートを特殊化できないのはなぜですか?

それがC++標準によって定められたルールだからです。

あなたが望むものに関しては、より良いアプローチは、関数の特殊化ではなく、関数のオーバーロードを次のように使用することです。

class surfaceMesh 
{
    public:
        // Uncomment for Version 0 and 1
        class AREA_AVERAGE {};
        class ANGLE_AVERAGE {};  

        template<class Average>
        void vertexNormals() 
        {
           //invoke the function overload
           vertexNormals(static_cast<Average*>(0));
        }
private:
        //make the overloads private, so client will not call them!
        void vertexNormals(AREA_AVERAGE *)
        {
           std::cout << "AREA_AVERAGE" << std::endl;
        }
        void vertexNormals(ANGLE_AVERAGE*)
        {
           std::cout << "ANGLE_AVERAGE " << std::endl;
        }
};

のタイプはstatic_cast<Average*>(0)、コンパイラーが正しいオーバーロードを選択するのに役立ちます。

于 2012-06-04T08:57:16.320 に答える