3

I have a template class called Temp, and it have a method takes an argument of the same type:

#ifndef TEMP_H
#define TEMP_H

template<class T>
class Temp
{
    public:
        T data;
        bool comp(T);
};
template<class T>
bool Temp<T>::comp(T data)
{
    return (this -> data < data);
}
#endif // TEMP_H

now I want to make an object of class Temp with type of pointer to another class called Foo.

Temp<Foo*> TptrF;

usually this is easy and for the method comp, I can do a specialization for this specific type Foo*, but I have to include the file Foo.h in Temp.h:

//Temp.h
#ifndef TEMP_H
#define TEMP_H
#include "Foo.h"

template<class T>
class Temp
{
    public:
        T data;
        bool comp(T);
};
template<class T>
bool Temp<T>::comp(T data)
{
    return (this -> data < data);
}
template<>
inline bool Temp<Foo*>::comp(Foo* data)
{
    return (this -> data -> val < data -> val);
}
#endif // TEMP_H

but the problem is that Foo class have an object of type Temp<int> and for this data member in Foo I have to include the file Temp.h in Foo.h:

//Foo.h
#ifndef FOO_H
#define FOO_H
#include "Temp.h"

class Foo
{
    public:
        int val;
        Temp<int> Ti;
};

#endif // FOO_H

this gives me in Foo.h:

error: 'Temp' does not name a type

I tried to remove #include "Foo.h" from Temp.h and use a forward declaration instead like class Foo;, but it didn't work as I used the 'val' data member of class Foo in the comp function, and it gives me in Temp.h:

error: invalid use of incomplete type 'class Foo'

and tried to remove #include "Temp.h" from Foo.h, and use a forward template declaration instead like template<class T> class Temp;,I thought this will work as I just need an object so I just want the compiler to know that I have a template class called Temp, but it also didn't work, and it give me in Foo.h:

error: field 'Ti' has incomplete type Temp<int>

What should I do to make this code work? Temp<int> and Temp<Foo*> do not contain each other as objects, so I believe this should work logically, or is it just one of the consequences of bad design.

lacse
  • 33
  • 3
  • My bad, I first though forward dec would solve it, only to see `this -> data -> val` afterward. The specialization `Temp` actually needs the _definition_ of `Foo`. – YSC Dec 11 '18 at 15:35

2 Answers2

1

Get rid of the declaration of comp specialized with the type Foo in Temp.h and overload operator< in Foo:

class Foo
{
public:
    int val;
    Temp<int> Ti;
    bool operator<(const Foo& f) {
      return val < f.val;
    }
};

I'm just typing this in so hopefully this compiles.

  • This will compiles **but**, Unfortunately the overloaded operator will never called because it compares tow _objects_, and the comp function compare tow _pointers to object_, and as a result it will compare tow addresses of memory instead of comparing the val data member. This will be helpful in case of template of type of another _object_, but not this one, template of type of _pointer_ to another object. – lacse Dec 11 '18 at 16:57
  • Ah, sure. Just change `const Foo&` to `Foo*` and `f.val` to `f->val` and it should be work fine. – Chad Seibert Dec 11 '18 at 17:06
  • man, are you sure of what you taking, because this operator will be called when comparing _object_ to pointer not _pointer_ to pointer, thus it will not be useful in this case too. – lacse Dec 11 '18 at 19:38
1

This needs to know what Foo is to compile data->val. So just move this to Foo.h

class Foo {
...
};

template<>
inline bool Temp<Foo*>::comp(Foo* data)
{
    return (this -> data -> val < data -> val);
}

Ref: https://gcc.godbolt.org/z/Go0-Zs

balki
  • 26,394
  • 30
  • 105
  • 151
  • Yep! I didn't know that I can write a specialization of a method in another file, that was helpful Thanks. – lacse Dec 11 '18 at 19:43