0

I'm trying to have a templated class (here C) that inherits from another templated class (here A) and perform static member specialization (of int var here), but I cant get the right syntax to do so (if it's possible

#include <iostream>

template<typename derived>
class A
{
    public:
        static int var;
};

//This one works fine
class B
    :public A<B>
{
    public:
        B()
        {
            std::cout << var << std::endl;
        }
};
template<>
int A<B>::var = 9;

//This one doesn't works
template<typename type>
class C
    :public A<C<type> >
{
    public:
        C()
        {
            std::cout << var << std::endl;
        }
};
//template<>
template<typename type>
int A<C<type> >::var = 10;

int main()
{
    B b;
    C<int> c;
    return 0;
}

I put an example that works with a non templated class (here B) and i can get the static member specialization of var, but for C that just doesn't work.

Here is what gcc tells me :

test.cpp: In constructor ‘C<type>::C()’:
test.cpp:29:26: error: ‘var’ was not declared in this scope
test.cpp: At global scope:
test.cpp:34:18: error: template definition of non-template ‘int A<C<type> >::a’

I'm using gcc version 4.6.3, thanks for any help

b3nj1
  • 667
  • 1
  • 6
  • 17

2 Answers2

0

You can hint the compiler that var is a member variable by writing this->var.

You can't write a template to define the static members of the template specialisation A<C<type>>; when you define a static member you're reserving storage but writing a template partial specialisation doesn't tell the compiler which full specialisations to reserve storage for. The best you can do is to write

template<>
int A<C<int> >::var = 10;

An alternative would be to use a function-level static accessed via a template function:

template<typename T> class A {
    static int &var() { static int var; return var; }
};
ecatmur
  • 152,476
  • 27
  • 293
  • 366
  • "I don't think there is any way to partially specialise a template class static member"?? What is the problem? Type of the static member can depend on params of the template in any way author wants... (close to downvote. Please, fix this) – Kirill Kobelev Jul 11 '12 at 09:14
  • @KirillKobelev bad wording; the issue is *defining* the static member (which can only be done for a full specialisation). Please take a look. – ecatmur Jul 11 '12 at 09:20
  • It is much better now. Thanks. – Kirill Kobelev Jul 11 '12 at 09:22
0

I suggest you use an enum in the parent class and set the value from the child class as a template parameter to the parent. For class C to 'see' var, it can be qualified. See below:

#include <iostream>
using namespace std;

template<typename Child, int i = 0> // 0 is the default value
class A
{
    public:
        enum { var = i };
};

class B
    :public A<B>   // define the value or var here
{
    typedef A<B> Parent;
public:
    B()
    {
        cout << Parent::var << endl; // Parent:: here IS NOT necessary, just for uniformity's sake
    }
};

template<typename type>
class C
    :public A<C<type>, 200>  // define the value of var here
{
    typedef A<C<type>, 200> Parent;
public:
    C()
    {
        cout << Parent::var << endl; // Parent:: here IS necessary
    }
};


int main()
{
    cout << B::var << endl;
    cout << C<int>::var << endl;
    cout << C<char>::var << endl;
}
bancsy
  • 142
  • 1
  • 6
  • I have a set of classes that are templated or not (on "type" here) and these classes must have a static member, so I'm using a base class that declares this static member (and some more stuff) and with static member specialization i define it in the subclasses. But for the templated classes (like in the example) this doesn't work :/ – b3nj1 Jul 11 '12 at 10:30
  • i see, i amended my answer to address what you are trying to do. – bancsy Jul 13 '12 at 02:59