Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > static const int problem

Reply
Thread Tools

static const int problem

 
 
Salt_Peter
Guest
Posts: n/a
 
      05-15-2007
On May 15, 8:04 am, Markus Moll <(E-Mail Removed)> wrote:
> Hi
>
> Lionel B wrote:
> > On Tue, 15 May 2007 12:31:02 +0100, Zeppe wrote:
> >> Even if you perform the initialization inside the class declaration, you
> >> still need the definition of the static member variable on a cpp file.

>
> > I don't believe you do need that for a static integer constant declared
> > and initialised within a class. I think the OP is either not telling the
> > whole story or else his/her compiler is badly broken.

>
> Believe it or not:
> (9.4.2 (4)): "If a static data member is of const integral or const
> enumeration type, its declaration in the class definition can specify a
> constant-initializer which shall be an integral constant expression


The operative word here is class 'definition'.
Not to be confused with the class declaration.

> (5.19). In that case, the member can appear in integral constant
> expressions. The member shall still be defined in a namespace scope if
> it is used in the program and the namespace scope definition shall not
> contain an initializer."
>
> Markus



 
Reply With Quote
 
 
 
 
Ron Natalie
Guest
Posts: n/a
 
      05-15-2007
Salt_Peter wrote:

> The operative word here is class 'definition'.
> Not to be confused with the class declaration.
>

Perhaps you are confused. The line in question
is in the class definition.
 
Reply With Quote
 
 
 
 
Lionel B
Guest
Posts: n/a
 
      05-15-2007
On Tue, 15 May 2007 13:44:30 +0100, Zeppe wrote:

> Lionel B wrote:
>
>> Strange thing is my gcc 4.1.2 compiles the problem code ok:
>>
>> g++-4.1.2 --version
>> g++-4.1.2 (GCC) 4.1.2
>>
>> whereas the OP's doesn't (perhaps it uses a different stdc++ lib ?).
>> Might be worth asking on the gcc lists, I guess.
>>
>>

> Well, that's strange indeed, because it seems that I'm using the same
> version as you. Probably the problem relies in the type of v.begin()
> that in different architectures has got different definitions. Anyway,
> I'm using (g++ -v)
>
> Using built-in specs.
> Target: i486-linux-gnu
> Configured with: ../src/configure -v
> --enable-languages=c,c++,fortran,objc,obj-c++,treelang --prefix=/usr
> --enable-shared --with-system-zlib --libexecdir=/usr/lib
> --without-included-gettext --enable-threads=posix --enable-nls
> --program-suffix=-4.1 --enable-__cxa_atexit --enable-clocale=gnu
> --enable-libstdcxx-debug --enable-mpfr --enable-checking=release
> i486-linux-gnu
> Thread model: posix
> gcc version 4.1.2 (Ubuntu 4.1.2-0ubuntu4)


Here's mine (never mind the odd paths):

Using built-in specs.
Target: x86_64-unknown-linux-gnu
Configured with: /var/scratch/lionelb/usr/src/gcc-4.1.2/configure --
prefix=/var/scratch/lionelb/opt/gcc-4.1.2 --enable-languages=c,c++ --with-
gnu-as --with-as=/var/scratch/lionelb/opt/binutils-2.17/bin/as --with-gnu-
ld --with-ld=/var/scratch/lionelb/opt/binutils-2.17/bin/ld --enable-
version-specific-runtime-libs --with-build-time-tools=/var/scratch/
lionelb/opt/binutils-2.17/bin
Thread model: posix
gcc version 4.1.2

> and the command line to compile is
>
> g++ -Wall teststatic.cpp -o teststatic


Same here.

Compiles ok too with the Intel compiler icc 9.0 and Comeau online.

--
Lionel B
 
Reply With Quote
 
Juha Nieminen
Guest
Posts: n/a
 
      05-15-2007
Lionel B wrote:
>> Even if you perform the initialization inside the class declaration, you
>> still need the definition of the static member variable on a cpp file.

>
> I don't believe you do need that for a static integer constant declared
> and initialised within a class. I think the OP is either not telling the
> whole story or else his/her compiler is badly broken.


I think that the idea of requiring an actual instance of the const
variable is that some code might want to create a pointer to it.

OTOH, isn't this a problem only if the const variable is public?
If it's private then I can't think of any situation where the
compiler couldn't detect an attempt to create a pointer to it at
compile time. (The problem with a public const variable is that
this public const might be in a library, and some program using
that library might want to create the pointer, in which case a
linker error will happen and it will basically be impossible to
do that. However, with a private const I don't think this could be
possible...)
 
Reply With Quote
 
Salt_Peter
Guest
Posts: n/a
 
      05-15-2007
On May 15, 9:13 am, Ron Natalie <(E-Mail Removed)> wrote:
> Salt_Peter wrote:
> > The operative word here is class 'definition'.
> > Not to be confused with the class declaration.

>
> Perhaps you are confused. The line in question
> is in the class definition.


Yes it is and no i'm not confused.

 
Reply With Quote
 
mati
Guest
Posts: n/a
 
      05-15-2007
mati wrote:
> Hi
> (...)
> Can anybody tell me what I'm doing wrong?


Thanks for answering, now I know (or at least I think so) everything.
Short: The rhs argument of random iterator's operator+ is const &, and
if there is no namespace scope definition of static const int member,
the linker fails.
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      05-16-2007
On May 15, 2:44 pm, Zeppe
<zeppe@.remove.all.this.long.comment.email.it> wrote:
> Lionel B wrote:
> > Strange thing is my gcc 4.1.2 compiles the problem code ok:


> > g++-4.1.2 --version
> > g++-4.1.2 (GCC) 4.1.2


> > whereas the OP's doesn't (perhaps it uses a different stdc++ lib ?).
> > Might be worth asking on the gcc lists, I guess.


> Well, that's strange indeed, because it seems that I'm using the same
> version as you. Probably the problem relies in the type of v.begin()
> that in different architectures has got different definitions. Anyway,
> I'm using (g++ -v)


> Using built-in specs.
> Target: i486-linux-gnu
> Configured with: ../src/configure -v
> --enable-languages=c,c++,fortran,objc,obj-c++,treelang --prefix=/usr
> --enable-shared --with-system-zlib --libexecdir=/usr/lib
> --without-included-gettext --enable-threads=posix --enable-nls
> --program-suffix=-4.1 --enable-__cxa_atexit --enable-clocale=gnu
> --enable-libstdcxx-debug --enable-mpfr --enable-checking=release
> i486-linux-gnu
> Thread model: posix
> gcc version 4.1.2 (Ubuntu 4.1.2-0ubuntu4)


> and the command line to compile is


> g++ -Wall teststatic.cpp -o teststatic


And you get the error, or no?

Formally, not providing the definition is undefined behavior.
Practically, in this particular case, I would not expect there
to be a problem, unless the compiler explicitly does something
special to make it one (so that a program with undefined
behavior doesn't compile). (I wonder if the
"--enable-checking=release" has something to do with it.)

Another issue could be the library. If the address of the
constant is ever taken (including implicitly, e.g. by using it
as an argument for a reference parameter), then it will almost
certainly need a definition. If vector<>::iterator is a class
type (normally the case today, I think, and certainly the case
with g++), and the operator+ takes a reference (which seems
surprising to me, but perhaps there are reasons), and ptrdiff_t
(the type which is added to an iterator) is int, then the
address will be taken. (If ptrdiff_t is not int, then his
static const will first be converted to a temporary ptrdiff_t;
this conversion almost surely doesn't involve taking the
address.)

A quick check in the sources of g++ 4.1.0 show:
__normal_iterator
operator+(const difference_type& __n) const
{ return __normal_iterator(_M_current + __n); }
The operator+ does take a reference, so on machines where
ptrdiff_t (the type of difference_type by default, with the
default allocator) is int, the address of his static const will
be taken, and he must define it. Unless the compiler actually
inlines the function---if he turns on optimization, he might not
need to define it. (On my machines, ptrdiff_t is almost
always a long, so I wouldn't have to define it either.)

But whatever: the rules say you have to define it, or you have
undefined behavior. And defining it always works. So it's
obvious what you have to do when writing code.

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

 
Reply With Quote
 
Zeppe
Guest
Posts: n/a
 
      05-16-2007
James Kanze wrote:
> On May 15, 2:44 pm, Zeppe
> <zeppe@.remove.all.this.long.comment.email.it> wrote:
>> Well, that's strange indeed, because it seems that I'm using the same
>> version as you. Probably the problem relies in the type of v.begin()
>> that in different architectures has got different definitions. Anyway,
>> I'm using (g++ -v)

>
>> Using built-in specs.
>> Target: i486-linux-gnu
>> Configured with: ../src/configure -v
>> --enable-languages=c,c++,fortran,objc,obj-c++,treelang --prefix=/usr
>> --enable-shared --with-system-zlib --libexecdir=/usr/lib
>> --without-included-gettext --enable-threads=posix --enable-nls
>> --program-suffix=-4.1 --enable-__cxa_atexit --enable-clocale=gnu
>> --enable-libstdcxx-debug --enable-mpfr --enable-checking=release
>> i486-linux-gnu
>> Thread model: posix
>> gcc version 4.1.2 (Ubuntu 4.1.2-0ubuntu4)

>
>> and the command line to compile is

>
>> g++ -Wall teststatic.cpp -o teststatic

>
> And you get the error, or no?


Yes, I do.

> Formally, not providing the definition is undefined behavior.


Well, actually I'm a little bit confused. And, strangely enough, it's
the Stroustrup that confuses me more than the standard. The standard says:

In that case [static member initialized in the class definition], the
member can appear in integral constant expressions within its scope. The
member shall still be defined in a namespace scope if it is used in the
program and the namespace scope definition shall not contain an initializer.

Which is clear enough, and it seems to suggest that if you define the
member in the namespace scope you never get wrong. In the Stroustrup,
anyway, it says (very concisely, as usual in the Stroustrup):

If (and only if) you use an initialized member in a way that requires it
to be stored as an object in memory, the member must be (uniquely)
defined somewhere.

I can't understand the "and only if". What does it happen if I define it
anyway? Is there some drawback?

> Practically, in this particular case, I would not expect there
> to be a problem, unless the compiler explicitly does something
> special to make it one (so that a program with undefined
> behavior doesn't compile). (I wonder if the
> "--enable-checking=release" has something to do with it.)
>


The problem disappears by enabling some optimizations (-O2). I couldn't
discover which one was the responsible, though, because when I enabled
the optimizations singularly the error was still there.

> Another issue could be the library. If the address of the
> constant is ever taken (including implicitly, e.g. by using it
> as an argument for a reference parameter), then it will almost
> certainly need a definition. If vector<>::iterator is a class
> type (normally the case today, I think, and certainly the case
> with g++), and the operator+ takes a reference (which seems
> surprising to me, but perhaps there are reasons), and ptrdiff_t
> (the type which is added to an iterator) is int, then the
> address will be taken. (If ptrdiff_t is not int, then his
> static const will first be converted to a temporary ptrdiff_t;
> this conversion almost surely doesn't involve taking the
> address.)


I think you are just right, unless some optimization just disables this
by passing by value the const ref, while expanding the inline function
operator+ (at least in the machines in which sizeof(int) == sizeof(int*)).

> But whatever: the rules say you have to define it, or you have
> undefined behavior. And defining it always works. So it's
> obvious what you have to do when writing code.



I agree with you. Just that small thing at the beginning of the post
creates me some doubts...

Regards,

Zeppe
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      05-16-2007
On May 16, 11:52 am, Zeppe
<zeppe@.remove.all.this.long.comment.email.it> wrote:
> James Kanze wrote:
> > On May 15, 2:44 pm, Zeppe
> > <zeppe@.remove.all.this.long.comment.email.it> wrote:


[...]
> > Formally, not providing the definition is undefined behavior.


> Well, actually I'm a little bit confused. And, strangely enough, it's
> the Stroustrup that confuses me more than the standard. The standard says:


> In that case [static member initialized in the class definition], the
> member can appear in integral constant expressions within its scope. The
> member shall still be defined in a namespace scope if it is used in the
> program and the namespace scope definition shall not contain an initializer.


> Which is clear enough, and it seems to suggest that if you define the
> member in the namespace scope you never get wrong.


More to the point, it says that if you don't the code is wrong,
even if you don't get an immediate error.

> In the Stroustrup,
> anyway, it says (very concisely, as usual in the Stroustrup):


> If (and only if) you use an initialized member in a way that requires it
> to be stored as an object in memory, the member must be (uniquely)
> defined somewhere.


> I can't understand the "and only if". What does it happen if I define it
> anyway? Is there some drawback?


Two points:

-- first, Bjarne understands too much about how compilers
work---his statement reflects the reality of what
compilers give you, not the words in the standard. and

-- I think you're missing a subtility in his statement: his "if
and only if" applies to "must"; in English, the opposite of
"must" isn't "must not", but "don't have to"; the absolute
requirement is present "if and only if", but it's always
acceptable to declare the variable.

In fact, I would consider this an error in his text, since it
contradicts the standard, even if it is conform with regards to
actual practice. But in the end, it doesn't matter: it's never
wrong to define the variable, it never causes problems, and as
we've just seen, it's not always obvious whether the variable
has been declared in such a way as to require it to be stored in
memory---in the case in question, for example, that actual
function which took the reference was inline, and if the
compiler actually inlined it (which it probably would do if you
demand optimization), the need for the in memory object could
disappear.

--
James Kanze (Gabi Software) email: http://www.velocityreviews.com/forums/(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

 
Reply With Quote
 
cathode26@gmail.com
Guest
Posts: n/a
 
      07-28-2013
On Tuesday, May 15, 2007 6:17:01 AM UTC-5, mati wrote:
> Hi
>
> The following code works:
>
> #include <vector>
> class C {
> private:
> static const int m_static = 2;
> public:
> void f(const std::vector<int>& v)
> {
> int a = m_static;
> std::vector<int> stripped(v.begin()+a, v.end());
> //std::vector<int> s2(v.begin()+m_static,v.end());
> }
> };
> int main()
> {
> C c;
> std::vector<int> pv;
> int i;
> pv.push_back(i);
> pv.push_back(i);
> pv.push_back(i);
> c.f(pv);
> }
>
>
> But when I erase the comment in the void f(...), then compiler gives an
> error:
>
> g++ -ansi -Wall -o test test.cpp
> /tmp/cckLnGUY.o: In function `C::f(std::vector<int, std::allocator<int>
> > const&)':

> test.cpp.text._ZN1C1fERKSt6vectorIiSaIiEE[C::f(std::vector<int,
> std::allocator<int> > const&)]+0xdb): undefined reference to `C::m_static'
> collect2: ld returned 1 exit status
> make: *** [test] Error 1
>
> g++ --version
> g++ (GCC) 4.1.2 20060928 (prerelease) (Ubuntu 4.1.1-13ubuntu5)
>
>
> Can anybody tell me what I'm doing wrong?


So I tried your code in Visual Studio and it works fine, but if you use http://codepad.org/ your code does not compile. It is true, this is a declaration and not a definition. You need to define it like so.

#include <vector>

class C {
private:
static const int m_static = 2;
public:
void f(const std::vector<int>& v);

};

const int C::m_static;

void C::f(const std::vector<int>& v)
{
int a = m_static;
std::vector<int> stripped(v.begin()+a, v.end());
std::vector<int> s2(v.begin()+m_static,v.end());
}

int main()
{
C c;
std::vector<int> pv;
int i;
pv.push_back(i);
pv.push_back(i);
pv.push_back(i);
c.f(pv);
}
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
"static const int" versus "const int" John Goche C++ 4 11-11-2011 07:41 PM
is const necessary in eg int compar(const void *, const void *) lovecreatesbeauty@gmail.c0m C Programming 26 11-10-2008 09:47 PM
const vector<A> vs vector<const A> vs const vector<const A> Javier C++ 2 09-04-2007 08:46 PM
Casting int'** to 'const int * const * const' dosn't work, why? Jonas.Holmsten@gmail.com C Programming 11 07-01-2007 06:16 PM
unsigned int const does not match const unsigned int Timo Freiberger C++ 3 10-30-2004 07:02 PM



Advertisments