Defining a Nested const static variable?

Nov 10, 2009 at 4:16pm
closed account (1yR4jE8b)
alright, so I have a class defined similar to:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
template <class T>
class Class<T>
{
public:
     //functions and other members...
private:
     class InnerClass
     {
     public:
          static const InnerClass variable;
     private:
          InnerClass();
          //more stuff
     }
     //rest of outer class
};


Now, outside of the class I am trying to define the value of the const variable
inside InnerClass.

1
2
template <class T>
const Class<T>::InnerClass Class::InnerClass::variable = InnerClass();


Doesn't work...Can I initialize a static const variable with the default constructor of a class if it is private? Am I just writing my statement wrong?
Nov 10, 2009 at 4:19pm
closed account (1yR4jE8b)
woops, forgot to add my semi-colon at the end of my InnerClass, but that was just a typo from copying it over.
Nov 10, 2009 at 4:21pm
closed account (1yR4jE8b)
ugh, and my variable inicialization should be

1
2
template <class T>
const Class<T>::InnerClass Class<T>::InnerClass::variable = InnerClass();
Nov 10, 2009 at 7:07pm
Initialization has to be moved to a .cpp file. It cannot be done inline in the header.
Nov 10, 2009 at 9:52pm
closed account (1yR4jE8b)
I thought Template Code needs to always be done inline? Why would my initialization need to be in a .cpp file if everything else can be done inline in my header?
Nov 11, 2009 at 12:52am
You can't inline templates, unless you have a compiler which supports the export keyword, which AFAIK, none of the popular compilers support it.
Nov 11, 2009 at 3:50am
@darkestfright:

That's one of my pet peeves about C++.

1
2
3
4
struct Foo {
   static const int Number = 5;  // Compiles just fine
   static const std::string String = "Hello World";  // Compile error... can't initialize in declaration
};


I'm guessing it has to do with the compiler needing to generate code to initialize the static in
the string case (ie, run a constructor), and putting it in a header is problematic since the compiler
will want to generate that code for every .cpp file that #includes the header.

Nov 11, 2009 at 4:13am
As for the original problem:

The problem here is that the class is nested in a template class. Remember that Class<int> is a completely different class than Class<float>.

The error is that this line doesn't really make much sense to the compiler:

1
2
template <class T>
const Class<T>::InnerClass Class::InnerClass::variable = InnerClass();


The whole idea with this line is that you're instantiating variable. The reason this doesn't work is because the above is a template, which doesn't instantiate anything.

Since Class<int> is different from Class<float> -- this means that each of those classes have their own 'variable'. The only way the compiler could really fullfill the above statement is to create an infinite number of 'variable's, one for each T. This, of course, is impossible.

What I suspected you could do, was instantiate a specific variable for T. Something like the following.

 
const Class<int>::InnerClass Class<int>::InnerClass::variable = InnerClass();


However I get errors even when I try that -- and I'm not sure why because it seems logical to me. In any event that's not much of a solution unless you want to restrict how many types of T there can be.
Nov 11, 2009 at 4:36am
well I would say that variable is const so you cannot modify it outside of the bit of the class constructor that is run during the instantiation of the class. also since your default constructor is private you cannot instantiate
1
2
template<class T>
Class<T>::InnerClass
unless you create a specific constructor and even then you could only instantiate InnerClass when you called that specific constructor.
That's my take at least..
Nov 11, 2009 at 12:52pm
Does InnerClass have to be templated? Right now, according to the declaration in the original post
it is, but nothing there shows that it has to be. Can you simply move InnerClass out of OuterClass?
That would solve the problem....
Nov 11, 2009 at 1:00pm
Ok, this at least compiles for me:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
template< typename T >
class OuterClass {
  public:
    class InnerClass {
      public:
        static const InnerClass variable;
    };
};

template<>
const OuterClass<int>::InnerClass OuterClass<int>::InnerClass::variable = OuterClass<int>::InnerClass();

int main() {
    OuterClass<int> oci;
}
Topic archived. No new replies allowed.