[GiNaC-list] Include Guards

Jason Dusek jason.dusek at gmail.com
Fri Jan 21 02:41:03 CET 2005


What if I define the symbol as a static variable in a class header?

// <Evil.h>
#include <one_of_everything>

class Evil
{
  public:
    static symbol x("x");
    void showMeTheEvil()
    {
      cout << x;
};
// </Evil.h>

// <even_more_evil.cpp>
#include <Evil.h>

int
main(int argc, char* argv)
{
  Evil evil;
  evil.showMeTheEvil();
}
// </even_more_evil.cpp>

I am fine with OO evil - making a global symbol server class, for
example - but I can brook no other evil!

_jason

On Thu, 20 Jan 2005 11:47:04 +0300, Sheplyakov Alexei
<varg at theor.jinr.ru> wrote:
> On Wed, Jan 19, 2005 at 03:55:19PM -0600, Jason Dusek wrote:
> > In the FAQ, they discuss a problem with multiple inclusions of a
> > header where global symbols are defined:
> 
> The problem has NOTHING to do with multiple inclusions of a
> header. The actual problem is declaration of global variables
> in different compilation units by inclusion a _single_ header
> file, like this:
> 
> // file bogus.h
> #ifndef VARGS_BOGUS_H
> #define VARGS_BOGUS_H
> #include <ginac/ginac.h>
> const GiNaC::symbol x("x");
> #endif
> 
> // file fun1.cpp
> #include <ginac/ginac.h>
> #include "bogus.h"
> const GiNaC::ex fun1() { return x; }
> 
> // file fun2.cpp
> #include <ginac/ginac.h>
> #include "bogus.h"
> const GiNaC::ex fun2() { return x; }
> 
> // file main.cpp
> #include <iostream>
> #include <ginac/ginac.h>
> using namespace std;
> using namespace GiNaC;
> extern const ex fun1();
> extern const ex fun2();
> 
> int main(int argc, char* argv)
> {
>         ex bogus = fun1() - fun2();
>         // print expression as a tree
>         cout << tree << bogus << endl;
>         return 0;
> }
> 
> On my system, this program will print
> 
> add @0x805ef88, hash=0xb7e7ae1a, flags=0x3, nops=2
>     x (symbol) @0x805eda8, serial=2, hash=0x670d3697, flags=0xf, domain=0
>     1 (numeric) @0x804fde8, hash=0x160af41d, flags=0xf
>     -----
>     x (symbol) @0x805ed70, serial=1, hash=0x79ba0000, flags=0xf, domain=0
>     -1 (numeric) @0x804fc58, hash=0xd60af41d, flags=0xf
>     =====
> 
> So, `bogus' is _not_ zero, because there are two _different_ symbols
> (with the same print-name x): one of them was defined in the file
> fun1.cpp, another -- in fun2.cpp. Note, that in this example header
> file "bogus.h" gets included only once.
> 
> > ================================================
> > Q: I have various modules, some global variables and...
> >
> > A: ...and you are getting weird results with symbols not being
> > identical? Imagine this situation: A file globals.h declares symbol
> > x("x"). Two other modules #include "globals.h", do something with
> > symbol x and return an expression ex containing the symbol to the
> > caller (e.g. to main()). When the caller combines the two expressions
> > there are really two different symbols both with the same print-name
> > x. This may cause terms like x-x to stay around which will never be
> > simplified to 0 because the system has no knowledge that the two
> > symbols are supposed to be the same. How should it? After all the
> > declarations really happend in different compilation units!
> > ================================================
> > Can include guards solve this problem?
> 
> No, they can't.
> 
> > Do I *have* to make that evil factory initializer thingy?
> 
> You might use something like
> 
> // file bogus.h
> #ifndef VARGS_GLOBAL_X_H
> #define VARGS_GLOBAL_X_H
> #include <ginac/ginac.h>
> extern GiNaC::symbol x;
> #endif
> 
> // file bogus.cpp
> #include <ginac/ginac.h>
> #include "bogus.h"
> using namespace GiNaC;
> symbol x("x");
> 
> // file fun1.cpp
> #include <ginac/ginac.h>
> #include "bogus.h"
> 
> const GiNaC::ex fun1() { return x; }
> 
> // file fun2.cpp
> #include <ginac/ginac.h>
> #include "bogus.h"
> 
> const GiNaC::ex fun2() { return x; }
> 
> // file main.cpp
> #include <iostream>
> #include <ginac/ginac.h>
> using namespace std;
> using namespace GiNaC;
> extern const ex fun1();
> extern const ex fun2();
> 
> int main(int argc, char* argv)
> {
>         ex bogus = fun1() - fun2();
>         // print expression as a tree
>         cout << tree << bogus << endl;
>         // will print zero
>         return 0;
> }
> 
> But (IMHO) such a code is even more evil :)
> 
> Best regards,
>         Alexei.
> 
> _______________________________________________
> GiNaC-list mailing list
> GiNaC-list at ginac.de
> http://thep.physik.uni-mainz.de/mailman/listinfo/ginac-list
> 


-- 
_jason



More information about the GiNaC-list mailing list