Linker error with static variable

I'm getting a curious linker error when passing a static member variable to std::min.

struct test
{      
      const static int val = 555;
};

int main()
{
      int x = std::min(344, test::val);
}

This causes a linker error with an undefined reference to test::val.  It's easy enough to work around - I can simply use a temporary like this:

      int x = std::min(344, int(test::val));

But why do I need to do this?  Is it something to do with std::min being a templated function?
chsalviaAsked:
Who is Participating?
 
ravenplConnect With a Mentor Commented:
If You declare const static simple type, and then initialize along with in declaration
the variable is not created in fact, therefore You can't take it's pointer or reference - which std::min wants.
0
 
Infinity08Commented:
struct test
{      
      const static int val;
};

const int test::val = 555;

int main()
{
      int x = std::min(344, test::val);
}
0
 
Infinity08Commented:
or alternatively :

struct test
{      
      const static int val = 555;
};

const int test::val;

int main()
{
     int x = std::min(344, test::val);
}


But the point is that you need to define the static member outside of the class/struct.
0
Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

 
chsalviaAuthor Commented:
I thought it wasn't necessary to declare static member variables outside of the class if the type is a POD.  

Also, I'm able to use the variable outside the class - the linker error only occurs when I pass it to std::min.  But why does passing the variable to std::min trigger the linker error?
0
 
evilrixConnect With a Mentor Senior Software Engineer (Avast)Commented:
This works fine on VC++2005 --> What platform/compiler are you using? It probably doesn't support in-place assignment (it was a late edition to the standard)


>> I thought it wasn't necessary to declare static member variables outside of the class if the type is a POD
Normally you don't -- unless it's a non const, non-pod non-intrinsic, but it might be an older compiler that doesn't support this part of the standard.
#include <algorithm>
 
struct test
{      
      const static int val = 555;
};
 
int main()
{
      int x = std::min(344, test::val);
}

Open in new window

0
 
Infinity08Connect With a Mentor Commented:
>> I thought it wasn't necessary to declare static member variables outside of the class if the type is a POD.  

A static member is declared inside the struct, but defined outside the struct :

        struct test
        {      
              const static int val;        // <--- declaration
        };
       
        const int test::val = 555;    // <--- definition

The reason it needs to be defined at file scope is because a static member variable are not part of the objects ... they are a separate entity with their own storage.


In C++, a struct is just a class with different access defaults (private vs. public). So, whether you use a struct or a class doesn't make a difference.


>> Also, I'm able to use the variable outside the class - the linker error only occurs when I pass it to std::min.  But why does passing the variable to std::min trigger the linker error?

That's probably due to the interpretation of this paragraph in the C++ standard :

        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 (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.
0
 
evilrixSenior Software Engineer (Avast)Commented:
>> If You declare const static simple type, and then initialize along with in declaration
Eh? You mean like http:#20736822 ?

Check out this tutorial on class member initialization.
http://www.devx.com/getHelpOn/10MinuteSolution/17298/1954
0
 
Infinity08Commented:
Clicked submit too early - here's the rest of the post :

Or more specifically, this part : "In that case, the member can appear in integral constant expressions."
When you use the static const int like this :

         std::cout << test::val;

there's no problem, since you're accessing it as a const integral expression. However, when using it with min, you try to take the reference of a const integral expression ... That's not possible ;)
0
 
Infinity08Commented:
>> This works fine on VC++2005

That means your compiler is "broken" ;) It doesn't follow the C++ standard ;)
0
 
evilrixSenior Software Engineer (Avast)Commented:
As usual it seems different compilers interpret that differently due to the ambiguity of the wording. Don't you just love the standard :)
0
 
evilrixSenior Software Engineer (Avast)Commented:
>> It [VC2005] doesn't follow the C++ standard
No way, I don't believe that for 1 moment ;-)
0
 
Infinity08Commented:
>> >> It [VC2005] doesn't follow the C++ standard
>> No way, I don't believe that for 1 moment ;-)

You have to admit it does something quite fishy there ... take a reference of a const integral EXPRESSION hehe
0
 
evilrixSenior Software Engineer (Avast)Commented:
The wording is slightly ambiguous IMO. I have to be honest I've never had a problem but then I don't often need to define class level constants.
0
 
Infinity08Commented:
Well, the only way VC2005 would be able to compile that code is if it interpreted the declaration as a definition :

        struct test
        {      
              const static int val = 555;    // <--- VC2005 sees this as a definition instead of a declaration
        };

which the standard clearly contradicts :

        The declaration of a static data member in its class definition is not a definition and may be of an
        incomplete type other than cv-qualified void. The definition for a static data member shall appear in a
        namespace scope enclosing the members class definition.


Or possibly VC2005 did some early optimization, which is equally bad ...
0
 
evilrixSenior Software Engineer (Avast)Commented:
I've just re-read that section in the standards doc and on reflection I do agree, it shouldn't compile.
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 (5.19).  In that
case, the member can appear in integral constant expressions.  The member shall still be defined in a name-
space scope if it is used in the program and the namespace scope definition shall not contain an initializer."

Open in new window

0
 
Infinity08Commented:
Thinking about it a bit more, I do agree that it is ambiguous though, because you can do this :

        const int &ref = 5;

just not this :

        struct test {      
              static const int val = 5;
        };

        const int &ref = test::val;

mmm ... long live the standard lol.
0
 
evilrixSenior Software Engineer (Avast)Commented:
>> mmm ... long live the standard lol.
Yes, we've spoken about this before -- a lot of it is subjective depending upon what phase the moon is currently in :)

You know this is all peetm's fault -- he's even admitted as much :)

BTW: Do you have the ANSI ISO number for the (various) C standard(s)? I don't have a copy of that (I have both 98 and 03 versions of C++) and I could do with acquiring a copy (hopefully online via Google).
0
 
Infinity08Commented:
The C standard : ISO/IEC 9899
C99 for example : ISO/IEC 9899:1999
0
 
evilrixSenior Software Engineer (Avast)Commented:
Ta very muchly.
0
 
evilrixSenior Software Engineer (Avast)Commented:
There are some interesting docs here: http://www.open-std.org/jtc1/sc22/wg14/www/docs/
0
 
Infinity08Commented:
The most interesting in that list is the n1124.pdf ... It differs very little from the "real" C99 doc.
0
 
evilrixSenior Software Engineer (Avast)Commented:
n1255.pdf interested me: CERT C Programming Language Secure Coding Standard
0
All Courses

From novice to tech pro — start learning today.