3

I can not access protected base type typedef on simple code in gcc:

#include <iostream>
#include <memory>
#include <map>

template <class X>
X& Singleton()
{
    static X x;
        return x;
}

template<class GUID_T, class MAP_T, class T>
class TypeFactory {
protected:
        bool ContainsInternal(MAP_T id) {
                auto it = types.find(id);
                return (it != types.end());
        }

        typedef GUID_T GUID;
        inline virtual MAP_T GetTypeID(GUID guid) = 0;
        std::map<MAP_T, T> types;
public :
        void Add(GUID guid, const T & value) {
                auto id = GetTypeID(guid);
                if(!ContainsInternal(id)) {
                        types.insert(std::make_pair(id, T(value)));
                }
        }

        bool Contains(GUID guid) {
                return ContainsInternal(GetTypeID(guid));
        }

        std::shared_ptr<T> Get(GUID guid) {
                auto id = GetTypeID(guid);
                std::shared_ptr<T> result;
                auto it = types.find(id);
                if(it != types.end()) {
                        result = std::make_shared<T>(it->second);
                }
                return result;
        }

        std::map<MAP_T, T> & GetAll() {
                return types;
        }
};

template<class T>
class IntTypeFactory : public TypeFactory<int, int, T> {
protected:
        inline virtual int GetTypeID(GUID guid) {
                return guid;
        }
};
class Type {
public: int a;
};

int main() {
        IntTypeFactory<Type> & Types (Singleton< IntTypeFactory<Type> >());
        IntTypeFactory<Type> & Types2 (Singleton< IntTypeFactory<Type> >());

        auto t_in = Type();
        t_in.a = 10;
        Types.Add(1, t_in);
        auto t_out = Types2.Get(1);
        std::cout << t_out->a << std::endl;
        return 0;
}

compiles and works for VS2010 btw... and works for GCC if I literally declare inline virtual int GetTypeID(int guid) { So what is wrong with my code for GCC how to make it see protected parent class typedef?

Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
myWallJSON
  • 9,110
  • 22
  • 78
  • 149
  • Possible duplicate: http://stackoverflow.com/questions/3639340/typedef-inheritance-from-a-pure-abstract-base – divanshu Jun 13 '13 at 21:49

1 Answers1

5

You have to qualify the GUID type name. The compiler will not look for unqualified names in base classes, and since it is neither available in the global namespace, nor as a type alias in IntTypeFactory, it will eventually complain about GUID being the name of a non-existing type:

template<class T>
class IntTypeFactory : public TypeFactory<int, int, T> {
protected:
    inline virtual int GetTypeID(
        typename TypeFactory<int, int, T>::GUID guid) {
//      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            return guid;
    }
};

MSVC does not implement the two-phase lookup for templates and always looks for names at instantiation time, which is why this compiles with VS2010. However, this behavior is not conforming to the Standard. GCC is correct.

Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
  • @myWallJSON: The one I've shown in the answer: write `typename TypeFactory::GUID` instead of just `GUID` – Andy Prowl Jun 13 '13 at 22:12
  • It is quite sad - that it is not a bug... http://ideone.com/ZOQzaR I hoped for more template shugar from c++... – myWallJSON Jun 13 '13 at 22:14
  • Another option is to use `using typename TypeFactory::GUID;` in the scope of the derived class: http://ideone.com/wOG44l — that's simpler if the name appears in more than one place. – celtschk Jun 14 '13 at 05:39