简体   繁体   中英

Why is it not allowed to specialize a member function template within a class?

When I try to specialize a public member function template within the class definition/declaration:

#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;
}

For Version 0, the error is:

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()’

Version 1 compiles and runs. Of course, usually I am separating the class declaration and definition, but I would really like to know why this happens.

Also, is this a good way to specialize an interface? The other option would be to overload the function vertexNormals to take an object of AREA_AVERAGE or ANGLE_AVERAGE, but this is just a type telling me which kind of function I will be using, it is not supposed to be instantiated, so using templates 'feels' like a right choice.

Why is it not allowed to specialize a member function template within a class?

Because that is the rule laid down by the C++ Standard.

As for what you want, a better approach is to use function overload rather than function specialization as:

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;
        }
};

The type of the expression static_cast<Average*>(0) helps the compiler to choose the correct overload.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM