简体   繁体   中英

namespaced class template inheritance in C++

In an earlier question, I asked asked class template inheritance in C++ .

I now have an extra level to add!

Consider the following code. (Assume the member definitions are present and accurate)

namespace Game
{
    namespace Object
    {
        template<typename T>
        class Packable
        {
        public:

            /**
             * Packs a <class T> into a Packet (Packet << T)
             * Required for chaining packet packing
             *************************************************/
            virtual sf::Packet& operator <<(sf::Packet& packet) = 0; // Work-horse, must be defined by child-class
            friend sf::Packet& operator <<(sf::Packet& packet, T &t);
            friend sf::Packet& operator <<(sf::Packet& packet, T *t);

            /**
             * Unpacks a <class T> from a Packet (Packet >> T)
             * Required for chaining packet unpacking
             *************************************************/
            virtual sf::Packet& operator >>(sf::Packet& packet) = 0; // Work-horse, must be defined by child-class
            friend sf::Packet& operator >>(sf::Packet& packet, T &t);
            friend sf::Packet& operator >>(sf::Packet& packet, T *t);

            /**
             * Unpacks a <class T> from a Packet (T <<= Packet)
             * Returns the <class T> for convienence
             *************************************************/
            //friend T& operator <<=(T t, sf::Packet& packet); // Returning reference to cut down on copying (they're already passing us our own copy)
            friend T& operator <<=(T &t, sf::Packet& packet);
            friend T* operator <<=(T *t, sf::Packet& packet);
        };
    }
}

And this Ship class inherits from Game::Object::Packable

class Ship : public Game::Object::Base<Ship>, public Game::Object::Packable<Ship>
{
    public:
        Ship( void );
        //...

        // For packing and unpackinng packets
        sf::Packet& operator <<(sf::Packet& packet);
        sf::Packet& operator >>(sf::Packet& packet);
}

What we're left with is the following error.

(null): "Game::Object::operator<<(sf::Packet&, Ship*)", referenced from:

I've come to the conclusion that it must have something to do with the use of namespaces. What is the solution to this if I wanted to retain the namespaces?

Here is an excerpt of the method definitions. Do I have to dereference the namespace? (I don't think that even means anything haha)

/**
 * Packs a <class T> into a Packet (Packet << T)
 * Required for chaining packet packing
 *************************************************/
template<class T>
sf::Packet& operator <<(sf::Packet& packet, T *t)
{
    // Call the actual one, but basically do nothing... this needs to be overrided
    return packet << *t;
}

template<class T>
sf::Packet& operator <<(sf::Packet& packet, T &t)
{
    // Call the pointer one, but basically do nothing... this needs to be overrided
    return packet << &t;
}

// ... other definitions etc.

The friend declaration (non-template non-member) does not match the befriended function templates. I would advice you to provide the implementation inside the class definition:

    template<typename T>
    class Packable
        friend sf::Packet& operator <<(sf::Packet& packet, T &t) {
           return packet << t;
        }
    //...

This allows for a free non-template function that will be generated by the compiler on demand. Other alternatives include befriending the template or the template specialization that you care about.

Of course, you can ignore friendship completely and just provide the templates at namespace level, since they are implemented in terms of a public function…


Related:

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