1

I do the following.

template <class C> class B{};

template <class X> 
struct  A{
  int member;
};

template <class Y> 
struct  A<B<Y>>{
    A(int n):member(n){}
};

int main(int, char**){}

I.e. class X may be template itself and for that case I want to have specialisation of class A template.
But compiler says:

d:\>g++ -std=gnu++11 -o spec.exe spec.cpp
spec.cpp: In constructor 'A<B<Y> >::A(int)':
spec.cpp:11:14: error: class 'A<B<Y> >' does not have any field named 'member'  

If class A<B<Y>> is totlally separate from A then all is correct and there may not be any members ofA. But I want specialisation of A. With all its content.
Or, may be, some specialized constructor for A for case when X is B<Y>.
How to implement?

OlegG
  • 975
  • 3
  • 10
  • 30

2 Answers2

2

Template specialisation is a completely different mechanism than inheritance. It does not extend the contents of the general template: it replaces them with new contents for the specialised case. So the compiler is right: your class A<B<Y>> does not have any field named member. It only has a constructor that takes an int and a few additional automatically generated functions (copy constructor, destructor and the like).

If you want to "inherit" the contents of the template, you have two options:

  • Copy everything from the template into the specialisation
  • Put the common contents in a base class and inherit from it

Depending on what you want to do, one of these options will be better than the other.

Gorpik
  • 10,940
  • 4
  • 36
  • 56
  • Incidentally, notice that your specialisation has no default constructor; if you want it, you will have to write it explicitly (maybe using the `default` keyword if your compiler supports C++11). – Gorpik Jan 04 '13 at 11:23
  • Why default constructor? What for? – OlegG Jan 04 '13 at 11:38
  • @OlegG Notice that I wrote "if you want it". The default constructor is the constructor that can be called with no arguments. As it is written now, `A> a;` would fail to compile, but this may be what you want, I don't know. – Gorpik Jan 04 '13 at 11:49
  • @Gorpink: And btw, inheritance of A does not give anything. If I write `template struct A1: public A>{ A1(int n):member(n){} };` then compiler says `error: class 'A1' does not have any field named 'member'` – OlegG Jan 04 '13 at 12:23
  • @OlegG: In the initialisation list of a constructor you cannot call the constructor of a data member in a base class. You can only call your base class(es) constructor(s) and your own data members constructors. – Gorpik Jan 04 '13 at 12:28
1

This is how to implement it:

template <class C> class B{};

template <class X>
struct  A{
  int member;
};

template <class Y>
struct  A<B<Y> >{ // A<
    int member;  // just add member here
    A(int n):member(n){}
};

when you implement class template specialization, then it's like you are defining a whole new class .

I guess what you are looking for is member function specialization, but this one doesn't support partial specialization, and if you are trying to specialize the contructor of a given template class, then this contructor must be implicitly-declared.

template <class C> class B{};

template <class X>
struct  A{
  A(int n); // I implicitly-declared the constructor that I want to specialize. 
            // you can still define it if you want.
  int member;
};
// this is the contructor specialization,
// Note this isn't partial specialization, it's explicit specialization so you
// must provide a type that you want to specialize it with, in this case B<int>
template <>
A<B<int> >::A(int n):member(n){}
AlexDan
  • 3,203
  • 7
  • 30
  • 46
  • two questions: 1) how to avoid implicit (may be explicit?) declaration of A(int) in class A? 2) I do not need A>::A(int) constructor. I do need A>::A(int) one. – OlegG Jan 04 '13 at 12:08
  • if you are going to explicitly specialize A(int) you can't avoid it's previous declaration in class template A. if you need B then I can't think of anything other than do a partial specialization of the whole class template A, as I've showed you in the 1st example since you can't do it if you want to specialize only the constructor of A. – AlexDan Jan 04 '13 at 12:11
  • adding member of A to A> means adding all content of A to A>. This is inappropriate. All I need is adding one special constructor to A which constructs A with parameter B. All these tadas are dedicated for that. – OlegG Jan 04 '13 at 12:16