Re: [ROOT] Unresolved reference and CINT

From: Christian Holm Christensen (cholm@hehi03.nbi.dk)
Date: Tue Jan 29 2002 - 15:28:27 MET


Hi Hermann-Josef, 

On Tue, 29 Jan 2002 13:43:20 +0100 (CET)
"mathes@ik.fzk.de" <mathes@ik3.fzk.de> wrote
concerning "Re: [ROOT] Unresolved reference and CINT":
> 
> Hi Christian,
> 
> thanks for the reply. Your suggestion was not what I indended to do but it
> helped me anyway ...
> 
> I wanted to have a constant in the 'namespace' of the class TEyeEventHeader
> and use it outside of this class as TEyeEventHeader::kTicksPerSecond.
> That is the reason why it was not named fgTicksPerSecond.
> 
> Well an appropriate solution could be:
> 
> class TEyeEventHeader : public TObject {
> public:
>     enum Constants {
>       kTicksPerSecond = 100000000
>     };
> 
>     ClassDef(TEyeEventHeader,(int)EyeEVENTVERSIONv1)
> };
> 
> or what do you think ?

If your member is indeed of `integer' type  (short, int, or long),
then you can use an `enum'.   However, the above actually introduces
another name space, since you've given the `enum' a name.  Consider 

  #include <iostream>

  class Foo 
  {
  private:
  public:
    enum Bar { 
      kBar = 100000 
    };
    enum {
      kBaz = 1000000000
    };
  };

  void Print(Foo::Bar bar) {
    cout << "Foo::Bar enumerator: " << bar << endl;
  }

  void Print(int baz) {
    cout << "int:                 " << baz << endl;
  }

  int main(int argc, char** argv) 
  {
    Print(Foo::kBar); 
    Print(Foo::kBaz);
    return 0;
  }

Compiling an running this gives: 

  Foo::Bar enumerator: 100000
  int:                 1000000000

so there's a difference between the two kinds of `enum'.  The named
`enum' diffines a type, while the unnamed defines a bit field (I
think).  Therefor, I suggest you use an unnamed `enum' if you want to
use `TEyeEventHeader::kTicksPerSecond' as a `integer' constant, rather
than a `TEyeEventHeader::Constants' value. 


> Probably declaration and definition of the member variable is
> something which is not generally allowed ?

What do you mean?  In section 9.2, paragraph 4, it says 

  A member-declarator can contain a constant-initializer only if it 
  declares a static member (9.4) of inte-gral or enumeration type, see 
  9.4.2.  

in Section 9.4.2, paragraph 4, it says 

  If a static data member is of const integral or const enumeration
  type, its declaration in the classdefinition can specify a
  constant-initializer which shall be an integral constant expression
  (5.19).  In thatcase, 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.

So, doing 

  #include <iostream>

  class Foo 
  {
  public:
    static const int fgFoo = 10;
  };

  main(int argc, char** argv) 
  {
    return Foo::fgFoo;
  }

is ok - hmm, which sort of begs the original question.   I tried the
above code using GCC versions 2.91.66, RedHat-2.96, and 3.0.2, and it
worked fine.  However, if I instead have the files foo.hh, foo.cc, and
main.cc with the contents 

  // foo.hh 
  class Foo {
  public:
    static const fgFoo = 10;
    Foo();
  };
  // EOF 

  // foo.cc 
  Foo::Foo() {}  
  // EOF 

  // main.cc 
  #inlcude "foo.hh"
  main(int argc, char** argv) 
  {
    return Foo::fgFoo;
  }
  // EOF

and I compile the class to a shared library, 

  g++ -c -fPIC -Wall foo.cc
  g++ -shared -Wl,-soname,libfoo.so -o libfoo.so foo.o 
  g++ -L. -lfoo -Wl,-rpath,. main.cc -o foo 

then listing the symbols in libfoo.so and foo (using nm -C) does not
show Foo::fgFoo, and I guess that's why the linker can't find in your
case.  However, moving the initialisation of fgFoo to foo.cc makes 
Foo::fgFoo visible in libfoo.so.  I can't tell you why the above
example works and yours doesn't.  It seems the compiler does some
inline substitution of the `static const' member or something.  Why
that doesn't work in your case, I don't know. 

Anyway, to get back to your statement above, the following is _not_
legal code: 

  class Bar {
  public:
    const int kBar = 10; 
  }; 

GCC complains, and asks you to make Bar::kBar static.  
 
Yours, 

Christian Holm Christensen -------------------------------------------
Address: Sankt Hansgade 23, 1. th.           Phone:  (+45) 35 35 96 91 
         DK-2200 Copenhagen N                Cell:   (+45) 28 82 16 23
         Denmark                             Office: (+45) 353  25 305 
Email:   cholm@nbi.dk                        Web:    www.nbi.dk/~cholm



This archive was generated by hypermail 2b29 : Sat Jan 04 2003 - 23:50:40 MET