0

I have the following code:

template <class T>
class Planet{
    protected:
        std::map<ID, std::shared_ptr<T>> population;
        ID freeId;
    public:
    //@todo dorobić name
        Planet();
        T& registerCitizen(std::string);
        T& findCitizen(ID);
        T& findCitizen(std::string);
};

template <class T>
class PairPlanet: public Planet<T>{
    public:
        T& registerCitizen(T&, T&);
};

The problem here is that PairPlanet seems not to inherit from planet: For example if I try to define: template

T& PairPlanet<T>::registerCitizen(T& per1, T& per2){
    T* new_person = new T(per1.citizenName+"&"+per2.citizenName,freeId);
    population.insert(std::pair<ID, T>(freeId, *new_person)).first;
    freeId++;
    return *new_person; 
};

I receive an information that both population and freeId are undefined. May I ask for some hints?

Matimath
  • 31
  • 1

1 Answers1

0

Short answer: You need to use an explicit this-> to refer to freeId and population:

template <class T>
T& PairPlanet<T>::registerCitizen(T& per1, T& per2){
    T* new_person = new T(per1.citizenName+"&"+per2.citizenName,
                          this->freeId);
    // The original had a pointless `.first` at the end,
    // but I removed it because it was pointless.
    this->population.insert(std::make_pair(this->freeId, *new_person));
    ++this->freeId;
    return *new_person; 
};

The reason is "non-dependent name lookup" (§14.6.3 [temp.nondep] of the current C++14 draft):

Non-dependent names used in a template definition are found using the usual name lookup and bound at the point they are used.

A non-dependent name is a name which doesn't visibly depend on a template parameter. The unqualified use of freeId and population is not visibly dependent on anything, so they are looked up "using the usual name lookup ... at the point they are used". In other words, the compiler resolves them at the point where they appear in the program text, during the definition of the PairPlanet template. They're not in the class itself nor in global scope, so it doesn't find them and complains.

Your intention was that freeId and population come from the base class, which is dependent on the template parameter. So you need to explicitly state that those identifiers are dependent, by showing that they are members of the object pointed to by this. For dependent names, the compiler uses the name lookup strategy from the next section of the standard, which defers name lookup until the point of instantiation when the template parameter is known. At that point, the compiler has worked out the definition of the base class, and the names defined in it are available for the lookup.

rici
  • 234,347
  • 28
  • 237
  • 341