Topic: Passing a static const class member as reference


Author: James Kanze <james.kanze@gmail.com>
Date: Wed, 28 Nov 2007 11:56:38 CST
Raw View
On Nov 27, 9:40 pm, andreytarasev...@hotmail.com (Andrey Tarasevich)
wrote:
> Vincent Rivi   re wrote:
> > ...
> > With GCC 3.4.4 and GCC 4.2.2, if fails at link time :
> > $ g++ tst.cpp -o tst
> > /tmp/ccym93Sz.o:tst.cpp:(.text+0x33): undefined reference to `A::C'
> > collect2: ld returned 1 exit status

> GCC is complaining correctly. In this case the static constant
> member object is 'used' and, therefore, has to be defined.

It's undefined behavior, so complaining is not required (but is
obviously highly desirable from a QoI point of view).

> > However, it works with Visual C++ 2005.

> Apparently, VC++ 2005 implements this as an extension. The
> important thing here is that the static object has to retain
> its "address identity" across all translation units. If you
> define several functions with a 'const int& i' parameters,
> which will print out the value of '&i' (address of 'i'), in
> different translation units and then call them with your
> static 'int' constant as an argument, all of them have to
> output the same address. VC++ 2005 seems to satisfy this
> requirement, which is why I call it an extension. Otherwise,
> it would be a bug.

Even if it didn't, that would just be a restriction or a
particularity of the extension.  The standard doesn't say what
happens if you don't define the static member, and returning a
random value for its address is certainly permissable.  It would
only be a bug if VC++ returned different addresses even when you
provided a definition.

In fact, of course, it can't be a bug, because nothing that a
compiler does in the presence of undefined behavior is a bug (at
least from the standards point of view).  Whether it's an
extension, or just a chance side effect of the way Microsoft
decided to implement static members, depends on whether it is
documented or not, and whether it is guaranteed to be available
in future versions (which perhaps use some different
implementation technique).

As extensions go, if it is an extension: like any extension, you
can't use it in portable code.  In this case, I don't think you
can turn it off, either, and it doesn't really provide any
useful additional functionality.  It's also easy to use
accidentally.  So basically, the only thing the extension does
is to lock you in to their compiler.

--
James Kanze (GABI Software)             email:james.kanze@gmail.com
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

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: vincent.riviere@freesbee.fr (=?ISO-8859-1?Q?Vincent_Rivi=E8re?=)
Date: Mon, 26 Nov 2007 17:54:05 GMT
Raw View
Hello.

Is the following program correct ?

class A
{
public:
     static const int C = 1;
};

void f(const int& i)
{

}

int main(int argc, char* argv[])
{
     f(A::C);

     return 0;
}


With GCC 3.4.4 and GCC 4.2.2, if fails at link time :
$ g++ tst.cpp -o tst
/tmp/ccym93Sz.o:tst.cpp:(.text+0x33): undefined reference to `A::C'
collect2: ld returned 1 exit status

However, it works with Visual C++ 2005.

Is it legal to pass a static const class member by reference to a function ?
If it is not, a compiler should complain at compile time, not at linking...

Vincent

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Greg Herlihy <greghe@mac.com>
Date: Mon, 26 Nov 2007 12:54:03 CST
Raw View
On Nov 26, 9:54 am, vincent.rivi...@freesbee.fr (Vincent Rivi   re)
wrote:
> Hello.
>
> Is the following program correct ?
>
> class A
> {
> public:
>      static const int C = 1;
>
> };
>
> void f(const int& i)
> {
>
> }
>
> int main(int argc, char* argv[])
> {
>      f(A::C);
>
>      return 0;
>
> }
>
> With GCC 3.4.4 and GCC 4.2.2, if fails at link time :
> $ g++ tst.cpp -o tst
> /tmp/ccym93Sz.o:tst.cpp:(.text+0x33): undefined reference to `A::C'
> collect2: ld returned 1 exit status
>
> However, it works with Visual C++ 2005.
>
> Is it legal to pass a static const class member by reference to a function ?

Yes, it is perfectly legal to pass a static class member by reference
to a function.

> If it is not, a compiler should complain at compile time, not at linking..

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: ok_nospam_ok@phoyd.net (Marco Manfredini)
Date: Mon, 26 Nov 2007 19:12:34 GMT
Raw View
Greg Herlihy wrote:
> On Nov 26, 9:54 am, vincent.rivi...@freesbee.fr (Vincent Rivi=E8re)

>> Is it legal to pass a static const class member by reference to a func=
tion ?
>=20
> Yes, it is perfectly legal to pass a static class member by reference
> to a function.

Compare 9.4.2/4: "...The member shall still be defined in a namespace=20
scope if it is used in the program and the namespace scope definition=20
shall not contain an initializer".

In other words:
class A
{
  public:
       static const int C =3D 1;
};
const int A::C; // required in this case

>=20
>> If it is not, a compiler should complain at compile time, not at linki=
ng..

The compiler can't complain at compile time, because the definition may=20
happen elsewhere.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: James Kanze <james.kanze@gmail.com>
Date: Tue, 27 Nov 2007 14:23:23 CST
Raw View
On Nov 26, 6:54 pm, vincent.rivi...@freesbee.fr (Vincent Rivi   re)
wrote:
> Is the following program correct ?

> class A
> {
> public:
>      static const int C = 1;
> };

> void f(const int& i)
> {
> }

> int main(int argc, char* argv[])
> {
>      f(A::C);
>      return 0;
> }

It has undefined behavior.  You declare a static member, but you
never define it.

> With GCC 3.4.4 and GCC 4.2.2, if fails at link time :
> $ g++ tst.cpp -o tst
> /tmp/ccym93Sz.o:tst.cpp:(.text+0x33): undefined reference to `A::C'
> collect2: ld returned 1 exit status

> However, it works with Visual C++ 2005.

Undefined behavior means that both of these behaviors are legal.
In some cases, it might even depend on the optimization level of
the compiler.

> Is it legal to pass a static const class member by reference
> to a function ?

Of course.

> If it is not, a compiler should complain at compile time, not
> at linking...

That's not the problem here.  The problem is that you have used
an object which has been declared, but have provided no
definition for it.  Which is undefined behavior: the compiler is
not required to diagnose an error, but it might.  Or it might
pass a reference to uninitialized memory to f, or an illegal
reference value, which triggered a core dump if accessed, or
just about anything else.

--
James Kanze (GABI Software)             email:james.kanze@gmail.com
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

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: andreytarasevich@hotmail.com (Andrey Tarasevich)
Date: Tue, 27 Nov 2007 20:40:31 GMT
Raw View
Vincent Rivi=E8re wrote:
> ...
> With GCC 3.4.4 and GCC 4.2.2, if fails at link time :
> $ g++ tst.cpp -o tst
> /tmp/ccym93Sz.o:tst.cpp:(.text+0x33): undefined reference to `A::C'
> collect2: ld returned 1 exit status

GCC is complaining correctly. In this case the static constant member
object is 'used' and, therefore, has to be defined.

> However, it works with Visual C++ 2005.

Apparently, VC++ 2005 implements this as an extension. The important
thing here is that the static object has to retain its "address
identity" across all translation units. If you define several functions
with a 'const int& i' parameters, which will print out the value of '&i'
(address of 'i'), in different translation units and then call them with
your static 'int' constant as an argument, all of them have to output
the same address. VC++ 2005 seems to satisfy this requirement, which is
why I call it an extension. Otherwise, it would be a bug.

> Is it legal to pass a static const class member by reference to a funct=
ion ?

Yes, it is.

--=20
Best regards,
Andrey Tarasevich

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: vincent.riviere@freesbee.fr (=?ISO-8859-1?Q?Vincent_Rivi=E8re?=)
Date: Tue, 27 Nov 2007 22:24:34 GMT
Raw View
> class A
> {
>  public:
>       static const int C = 1;
> };
> const int A::C; // required in this case

OK, I understand.
Static consts, even if initialized, must be defined outside the class
definition, just like not-const statics.

I see it applies to class templates, too.

template<int _C>
class A
{
public:
 static const int C = _C;
};

template<int _C>
const int A<_C>::C; // definition required

void f(const int& i)
{

}

int main(int argc, char* argv[])
{
 f(A<3>::C);

 return 0;
}

Is this the best way to "store" the integer template argument into the
class template in order to make it accessible from outside, like A<3>::C ?

Maybe it would be better to use an implicit inline accessor like:
 static int getC() { return _C; }
in order to avoid the static variable ?

Vincent

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]