static const int problem

Discussion in 'C++' started by mati, May 15, 2007.

  1. mati

    mati Guest

    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?
    mati, May 15, 2007
    #1
    1. Advertising

  2. mati

    Zeppe Guest

    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?


    Even if you perform the initialization inside the class declaration, you
    still need the definition of the static member variable on a cpp file.
    Strangely enough, visual studio compiles the code even without it.

    Regards,

    Zeppe
    Zeppe, May 15, 2007
    #2
    1. Advertising

  3. mati

    Hari Guest

    > Even if you perform the initialization inside the class declaration, you
    > still need the definition of the static member variable on a cpp file.
    > Strangely enough, visual studio compiles the code even without it.
    >
    > Regards,
    >
    > Zeppe


    Hmmm. I just tested code at: http://dinkumware.com/exam/Default.aspx
    on VC8, EDG and MINGW and every compiler make executable files. Maybe -
    ansi switch is using this error ?!
    Hari, May 15, 2007
    #3
  4. mati

    Lionel B Guest

    On Tue, 15 May 2007 13:17:01 +0200, mati wrote:

    > Hi
    >
    > The following code works:


    Um... no:

    main.cpp: In member function ‘void C::f(const std::vector<int, std::allocator<int> >&)’:
    main.cpp:10: error: ‘s2’ was not declared in this scope

    > #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());
    > };


    What's s2 ? ... ah, if you remove the "//" then suddenly it's a std::vector<int> ... and all compiles ok.

    --
    Lionel B
    Lionel B, May 15, 2007
    #4
  5. mati

    Lionel B Guest

    On Tue, 15 May 2007 11:41:00 +0000, Lionel B wrote:

    > On Tue, 15 May 2007 13:17:01 +0200, mati wrote:
    >
    >> Hi
    >>
    >> The following code works:

    >
    > Um... no:
    >
    > main.cpp: In member function ‘void C::f(const std::vector<int,
    > std::allocator<int> >&)’: main.cpp:10: error: ‘s2’ was not declared in
    > this scope
    >
    >> #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());
    >> };

    >
    > What's s2 ? ... ah, if you remove the "//" then suddenly it's a
    > std::vector<int> ... and all compiles ok.


    Sorry, disregard that (my newsreader wrapped the code peculiarly).

    Anyhow, with the line uncommented it compiles ok for me (gcc 3.4.6, gcc
    4.1.2 and Intel icc) - as it should. You don't need a separate definition
    for a static integer constant declared (and defined) as above.

    --
    Lionel B
    Lionel B, May 15, 2007
    #5
  6. mati

    Lionel B Guest

    On Tue, 15 May 2007 12:31:02 +0100, Zeppe wrote:

    > 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?

    >
    > 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.

    --
    Lionel B
    Lionel B, May 15, 2007
    #6
  7. mati

    Markus Moll Guest

    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
    (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
    Markus Moll, May 15, 2007
    #7
  8. mati

    Zeppe Guest

    Lionel B wrote:
    > 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.
    >


    Usually our knowledge breaks far before the compiler (I'm not being
    bumptious, I had to check as well because I thought the code was right
    at the beginning).

    Check out the Stroustrup at 10.4.6.2 or the standard at 9.4.2#4 for the
    rule. Basically, the problem is that the g++ doesn't recognise the
    expression "v.begin()+m_static" as a constant expression, and I think
    he's right in doing so (but not 100% sure).

    Regards,

    Zeppe
    Zeppe, May 15, 2007
    #8
  9. mati

    Lionel B Guest

    On Tue, 15 May 2007 13:19:06 +0100, Zeppe wrote:

    > Lionel B wrote:
    >> 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.
    >>

    > Usually our knowledge breaks far before the compiler (I'm not being
    > bumptious, I had to check as well because I thought the code was right
    > at the beginning).


    I think that's the politest manner I've ever been told I'm talking
    rubbish ;)

    > Check out the Stroustrup at 10.4.6.2 or the standard at 9.4.2#4 for the
    > rule.


    Wow, scary... I use class-initialised static int consts without separate
    definitions quite extensively and never had a compiler complain on me...

    > Basically, the problem is that the g++ doesn't recognise the
    > expression "v.begin()+m_static" as a constant expression, and I think
    > he's right in doing so (but not 100% sure).


    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.

    --
    Lionel B
    Lionel B, May 15, 2007
    #9
  10. mati

    Zeppe Guest

    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

    Regards,

    Zeppe
    Zeppe, May 15, 2007
    #10
  11. mati

    Salt_Peter Guest

    On May 15, 8:04 am, Markus Moll <> 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
    Salt_Peter, May 15, 2007
    #11
  12. mati

    Ron Natalie Guest

    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.
    Ron Natalie, May 15, 2007
    #12
  13. mati

    Lionel B Guest

    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
    Lionel B, May 15, 2007
    #13
  14. 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...)
    Juha Nieminen, May 15, 2007
    #14
  15. mati

    Salt_Peter Guest

    On May 15, 9:13 am, Ron Natalie <> 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.
    Salt_Peter, May 15, 2007
    #15
  16. mati

    mati Guest

    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.
    mati, May 15, 2007
    #16
  17. mati

    James Kanze Guest

    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:
    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
    James Kanze, May 16, 2007
    #17
  18. mati

    Zeppe Guest

    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
    Zeppe, May 16, 2007
    #18
  19. mati

    James Kanze Guest

    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:
    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
    James Kanze, May 16, 2007
    #19
  20. mati

    Guest

    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);
    }
    , Jul 28, 2013
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Timo Freiberger
    Replies:
    3
    Views:
    943
    Bob Hairgrove
    Oct 30, 2004
  2. Replies:
    11
    Views:
    1,101
  3. Javier
    Replies:
    2
    Views:
    561
    James Kanze
    Sep 4, 2007
  4. 0m
    Replies:
    26
    Views:
    1,115
    Tim Rentsch
    Nov 10, 2008
  5. John Goche
    Replies:
    4
    Views:
    612
    Victor Bazarov
    Nov 11, 2011
Loading...

Share This Page