another c++ q (with specialization and inheritance )
Oleg Goldshmidt
pub at goldshmidt.org
Tue Apr 28 16:03:35 IDT 2009
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 <erez0001 at gmail.com> 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 | pub at goldshmidt.org
More information about the Linux-il
mailing list