Reputation: 1356
I have a class with a private member (struct
) as follows:
enum indices {
zero,
one,
two,
...,
N
};
class myclass {
...
...
private:
struct impl;
impl* p_impl;
};
Then, in the implementation I have defined a static container (vector) in the struct as follows:
struct myclass::impl {
impl() : ... {
...
do_something;
...
}
...
...
static std::vector<std::string> v;
...
};
std::vector<std::string> myclass::impl::v = std::vector<std::string>(N); //-N is defined by an enum, say.
myclass::myclass() {
p_impl = new impl();
//-Is this where I should populate the static container?
impl::v[zero] = str0;
impl::v[one] = str1;
...
impl::v[N] = strN;
}
...
My questions are: Is the place where I have initialized the static container appropriate? If I moved the initializing of v
before allocating p_impl
, would it result in run-time errors? In other words, is there an order in which memory is assigned to the static members? Also, how can I make my container to be static const
without running into the errors described below?
Additional info:
When I tried to initialize it in the implementation but outside of the struct and any of the class members (and after the assignment that sets the size of the vector) as follows:
std::vector<std::string> myclass::impl::v = std::vector<std::string>(N); //-N is defined by an enum, say.
myclass::impl::v[zero] = str0;
myclass::impl::v[one] = str1;
...
myclass::impl::v[N] = strN;
then I get a build error on Windows (VC++ 2008):
error C2466: cannot allocate an array of constant size 0
This led me to place the initialization at the constructor of myclass
(seemed to be a natural place). Additionally, if I tried making the container a static const
, everything breaks with errors along the lines as follows.
error C2678: binary '=' : no operator found which takes a left-hand operand of type 'const std::basic_string<_Elem,_Traits,_Ax>' (or there is no acceptable conversion)
with
[
_Elem=char,
_Traits=std::char_traits<char>,
_Ax=std::allocator<char>
]
c:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\xstring(914): could be 'std::basic_string<_Elem,_Traits,_Ax> &std::basic_string<_Elem,_Traits,_Ax>::operator =(const std::basic_string<_Elem,_Traits,_Ax> &)'
with
[
_Elem=char,
_Traits=std::char_traits<char>,
_Ax=std::allocator<char>
]
c:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\xstring(919): or 'std::basic_string<_Elem,_Traits,_Ax> &std::basic_string<_Elem,_Traits,_Ax>::operator =(const _Elem *)'
with
[
_Elem=char,
_Traits=std::char_traits<char>,
_Ax=std::allocator<char>
]
c:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\xstring(924): or 'std::basic_string<_Elem,_Traits,_Ax> &std::basic_string<_Elem,_Traits,_Ax>::operator =(_Elem)'
with
[
_Elem=char,
_Traits=std::char_traits<char>,
_Ax=std::allocator<char>
]
while trying to match the argument list '(const std::basic_string<_Elem,_Traits,_Ax>, const std::string)'
with
[
_Elem=char,
_Traits=std::char_traits<char>,
_Ax=std::allocator<char>
]
Does anybody have an example of doing the same thing with a static const
container? Appreciate any thoughts and ideas as always. Thanks!
Upvotes: 0
Views: 1182
Reputation: 55395
Is the place where I have initialized the static container appropriate?
Yes, static data members of a class need a definition in namespace scope. But these
myclass::impl::v[zero] = str0;
myclass::impl::v[one] = str1;
...
myclass::impl::v[N] = strN;
are expressions, and they're not allowed in global scope. Compiler is trying to parse them as declarations, hence the error: "cannot allocate an array of constant size 0". You'll need to move this logic in a member function.
If I moved the initializing of v before allocating p_impl, would it result in run-time errors? In other words, is there an order in which memory is assigned to the static members?
Static members have external linkage, so they're guaranteed to be fully constructed before main() starts.
Also, how can I make my container to be static const without running into the errors described below?
You can only initialize a const
variable, not change it later. In C++11 you can do
std::vector<std::string> myclass::impl::v = { str0, str1, str2, ... };
Upvotes: 1