Erez, None of this is Linux-specific, maybe you should find a good C++ forum, e.g., comp.lang.c++.moderated? However, since you asked, here is an explanation.
You should understand the difference between definition and declaration, and also that if you define a template, then instantiate an object of the templatized class, and then try to specialize the template it will look as a redefinition of the class to the compiler. See below. Erez D <[email protected]> writes: > i am having problems compiling the following code: > ==================================== > #if 1 > template <class T> class c1 {}; > template <class T> class c2 : public c1<T> { public: c2(T &a); }; This is a *definition* of class c2<T>. Below you attempt to redefine it (rather than specialize it - this is because you instantiate it before specializing), and the compiler complains. > #else > template <class T> class c1; > template <class T> class c2; This is a forward declaration of class c2<T>. It is declared but not yet defined. When this preprocessor branch is active the definition below is OK. > #endif > template <> class c1<int> > { > int m_a; > public: > c1():m_a(0) {}; > c1(int a):m_a(a) {}; > c1(int &a):m_a(a) {}; > void set(const int a) {m_a=a;}; > const int get(void) const {return m_a;}; The first const is ignored since you are not returning a const value. The trailing ";" is also ignored (a recurring thing in your code). But this is irrelevant for the question at hand... > c2<int> gen_c2(int a) > { > c2<int> ret(a); This is where you *instantiate* an object of type c2<int>, so you cannot specialize the template later, as the compiler tells you. The cure also is logical. Declare the method here, and write the definition *after* specialization, i.e., put c2<int> c1<int>::gen_c2(int a) { c2<int> ret(a); return ret; } immediately before main(). > return ret; > } > const c1<int> &operator=(const c1<int> &other) {set(other.get()); > return *this;}; > }; > template <> class c2<int> : public c1<int> > { > public: > c2(int &a):c1(a) {}; I don't think this will compile (when you get to it) - c2 does not have a c1 member, which is what this notation exists for. Instead, c1(a) will be automatically called as the base class constructor, so you only need c2(int &a) {} if I understand your intention correctly. > }; > int main() > { > c1<int> a; > c2<int> b=a.gen_c2(); There is no c2<int> c1<int>::gen_c2(void). There is only c2<int> c1<int>::gen_c2(int). > } > =========================================== > if i compile it, i get: > file.cpp:27: error: specialization of ‘c2<int>’ after instantiation This is a precise statement - you only had to look for instantiation in your code - see above. > if on the other hand i change the #if 1 to #if 0, i get: > file.cpp: In member function ‘c2<int> c1<int>::gen_c2(int)’: > file.cpp:20: error: return type ‘struct c2<int>’ is incomplete Correct again - you have declared, but not defined c2<T>. Hope it helps, -- Oleg Goldshmidt | [email protected] _______________________________________________ Linux-il mailing list [email protected] http://mailman.cs.huji.ac.il/mailman/listinfo/linux-il
