Reputation: 1595
Consider the following header files.
In my Object.h
#ifndef OBJECT_H_
#define OBJECT_H_
#include <iostream>
template <class Policy>
class Object
{
friend Policy;
private:
Policy* p;
int hash;
public:
Object():p(new Policy(this)),hash(0){}
~Object(){delete p;}
void set(){p->setHash();}
void show() const{std::cout<<"hash = "<<hash<<std::endl;}
};
#endif // OBJECT_H_
Then I created two Policies, P1 and P2, with different hash values.
In p1.h
#ifndef P1_H_
#define P1_H_
template <class Policy> class Object;
class P1
{
enum {p1 = 1};
Object<P1>* t;
public:
P1(Object<P1>* at):t(at){}
void setHash(){t->hash = p1;}
};
#endif // P1_H_
In p2.h
#ifndef P2_H_
#define P2_H_
template <class Policy> class Object;
class P2
{
enum {p2 = 2};
Object<P2>* t;
public:
P2(Object<P2>* at):t(at){}
//void setHash(){t->hash = p2;} // ** Notice here **
};
#endif // P2_H_
In my main.cpp
I have
#include "Object.h"
#include "p1.h"
#include "p2.h"
int main()
{
Object<P1> t1;
t1.set();
t1.show();
Object<P2> t2;
//t2.set();
t2.show();
}
Result on OS X:
hash = 1
hash = 0
Observations:
It will compile and run properly. Notice the definition of Object<P2>
is even not complete. Since P2 have not defined setHash().
If I get rid of the comment in my main, then it will report an error.
./Object.h:20:8: error: no member named 'setHash' in 'P2'
main.cpp:12:6: note: in instantiation of member function 'Object::set' requested here t2.set();
Questions
Consider the Object member inside P1 or P2 class would compiler generate class definition for each of them even if I do not create an instance of Object<P1>
or Object<P2
in main?
Why Object<P2>
is OK? Since the definition is incomplete.
Upvotes: 0
Views: 71
Reputation: 106216
Consider the Object member inside P1 or P2 class would compiler generate class definition for each of them even if I do not create an instance of
Object<P1>
orObject<P2>
in main?
No. The members are Object<P1>* t;
and Object<P1>* t;
- they're not static
so are only created when P1
and P2
object instances are created, and they're pointers so even then no Object<P1>*
is created: the pointer passed to the constructor - which may be nullptr
/ 0
- is simply stored.
Why Object is OK? Since the definition is incomplete.
With templates, functions are only instantiated when called. As long as they can be parsed properly, it is not an error.
Upvotes: 1
Reputation: 120031
There are no Object<P1>
or Object<P2>
members inside P1
and P2
. There are Object<P1>*
and Object<P2>*
members. A pointer to an incomplete type is perfectly OK. The type itself will not be instantiated unless the pointer is dereferenced.
In your main
function, Object<P2>
is a complete type, but its non-virtual member functions are still not instantiated unless called (or rather, technically, ODR-used). This is why it is OK to have Object<P2> t2;
but calling t2.set()
is an error.
Upvotes: 1