Ambiguous expansion of macro 'ClassDef'


ROOT Version: 6.32.06
Platform: Ubuntu 22.04
Compiler: Not Provided


Hello all,
I’m following a tutorial provided by my prof to make my own EventClass. The header file is as follows:

#ifndef _MYEVENT_
#define _MYEVENT_
#include <iostream>
#include <vector>
#include "TObject.h"


class MyEvent{
 public:
  MyEvent(){ px = 0; py = 0; pt = 0;};
  virtual ~MyEvent(){};

  void setPx(float x_){ px = x_;};
  void setPy(float y_){ py = y_;};
  void setPt(float t_){ pt = t_;};

  float getPx(){return px;};
  float getPy(){return py;};
  float getPt(){return pt;};

 private:
  float px;
  float py;
  float pt;
  ClassDef(MyEvent,1)
};
#endif

I then go to my linux terminal and input:
root -l
.L MyEvent.h+
.L tree_example8.C

but i encounter a warning here, given by:

/home/amensaywho/ROOT_Tutorial/MyEvent.h:25:3: warning: ambiguous expansion of macro 'ClassDef' [-Wambiguous-macro]
  ClassDef(MyEvent,1)
  ^
/home/amensaywho/root/include/Rtypes.h:337:9: note: expanding this definition of 'ClassDef'
#define ClassDef(name,id)                            \
        ^
input_line_4:22:9: note: other definition of 'ClassDef'
#define ClassDef(name, id) \
        ^

the code for tree_example8.C is:

//Example of Tree using MyEvent Class 
#include "MyEvent.h"

void tree_example8() {

  TFile *f = new TFile("myfile_example8.root", "RECREATE");
  TTree *T = new TTree("T","tree with class");
  TRandom r;
  Float_t px,py,pt;

  MyEvent *event = new MyEvent();
  T->Branch("Event", "MyEvent", &event);

  for (Int_t i = 0; i < 10000; i++) {
    r.Rannor(px,py);
    pt = std::sqrt(px*px + py*py);
    
    event->setPx(px);
    event->setPy(py);
    event->setPt(pt);

    T->Fill();
  }
  
  f->Write();
  f->Close();
}

Can someone point out what I’m missing? I’ve read the manual and documentation but I’m kinda new to programming in general so the jargon is a bit beyond me…

Hello @amansas,

welcome to the ROOT forum!
In order to execute your macro you should run
.x tree_example8.C
I tried your code and it runs fine for me. Could you please retry executing with .x?

Monica

1 Like

I can not reproduce the problem with the code you provided. So there might be something odd with your ROOT installation. Let check a few things. On the shell prompt execute this following commands and give the output:

echo $ROOTSYS
which root.exe
g++ --version
cat $ROOTSYS/include/compiledata.h
ldd `which root.exe`
echo $PATH
echo $LD_LIBRARY_PATH

Ah ok, .x works for me, thank you. The steps we were asked to follow were:
.L MyEvent.h+
.L MyEvent_h.so
.L tree_example8.C
tree_example8()

Aren’t the last 2 steps equivalent to running .x tree_example8.C ? My warning pops up after .L tree_example8.C

.L MyEvent.h+
.L MyEvent_h.so

The .L ...so is redundant and is supposed to have been done already by the .L ...+

.L tree_example8.C
tree_example8()

This is meant to do exactly the same as

.x  tree_example8.C
2 Likes

I see. We were asked to run .L MyEvent_h.so everytime we quit root and wanted to run a macro that used the Event Class defined by MyEvent.h. Is that redundant as well?

Info for my ROOT Installation:

amensaywho@CONSOLE:~/ROOT_Tutorial$ echo $ROOTSYS
/home/amensaywho/root
amensaywho@CONSOLE:~/ROOT_Tutorial$ which root.exe
/home/amensaywho/root/bin/root.exe
amensaywho@CONSOLE:~/ROOT_Tutorial$ g++ --version
g++ (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

amensaywho@CONSOLE:~/ROOT_Tutorial$ cat $ROOTSYS/include/compiledata.h
/* This file is automatically generated */
#define BUILD_ARCH "linuxx8664gcc"
#define BUILD_NODE "Linux 4206edb925e4 4.18.0-553.16.1.el8_10.x86_64 #1 SMP Thu Aug 8 07:11:46 EDT 2024 x86_64 x86_64 x86_64 GNU/Linux"
#define CXX "c++"
#define COMPILER "/usr/bin/c++"
#define COMPILERVERS "gcc1140"
#define COMPILERVERSSTR "c++ (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0"
#define MAKESHAREDLIB  "cd $BuildDir ; c++ -fPIC -c $Opt -Wno-implicit-fallthrough -Wno-noexcept-type -pipe -W -Woverloaded-virtual -fsigned-char -pthread -std=c++17 $IncludePath $SourceFiles ; c++ $Opt $ObjectFiles -shared  -rdynamic $LinkedLibs -o $SharedLib"
#define MAKEEXE "cd $BuildDir ; c++ -c $Opt -Wno-implicit-fallthrough -Wno-noexcept-type -pipe -W -Woverloaded-virtual -fsigned-char -pthread -std=c++17 $IncludePath $SourceFiles; c++ $Opt $ObjectFiles  -rdynamic -o $ExeName $LinkedLibs"
#define CXXOPT "-O3 -DNDEBUG"
#define CXXDEBUG "-g"
#define ROOTBUILD ""
#define LINKEDLIBS "-L$ROOTSYS/lib -lCore -lRint "
#define INCLUDEPATH "-I$ROOTSYS/include"
#define OBJEXT "o"
#define SOEXT "so"
amensaywho@CONSOLE:~/ROOT_Tutorial$ ldd `which root.exe`
        linux-vdso.so.1 (0x00007ffc2a590000)
        libRint.so => /home/amensaywho/root/lib/libRint.so (0x00007effb9eda000)
        libCore.so => /home/amensaywho/root/lib/libCore.so (0x00007effb9a23000)
        libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007effb97ef000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007effb97cf000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007effb95a6000)
        /lib64/ld-linux-x86-64.so.2 (0x00007effb9f0f000)
        libpcre2-8.so.0 => /lib/x86_64-linux-gnu/libpcre2-8.so.0 (0x00007effb950d000)
        libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007effb94f1000)
        liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5 (0x00007effb94c6000)
        libxxhash.so.0 => /lib/x86_64-linux-gnu/libxxhash.so.0 (0x00007effb94b1000)
        liblz4.so.1 => /lib/x86_64-linux-gnu/liblz4.so.1 (0x00007effb9491000)
        libzstd.so.1 => /lib/x86_64-linux-gnu/libzstd.so.1 (0x00007effb93c2000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007effb92d9000)
amensaywho@CONSOLE:~/ROOT_Tutorial$ echo $PATH
/home/amensaywho/geant4/geant4-v11.2.2-install/bin:/home/amensaywho/root/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/lib/wsl/lib:/mnt/c/Windows/system32:/mnt/c/Windows:/mnt/c/Windows/System32/Wbem:/mnt/c/Windows/System32/WindowsPowerShell/v1.0/:/mnt/c/Windows/System32/OpenSSH/:/mnt/c/Program Files (x86)/NVIDIA Corporation/PhysX/Common:/mnt/c/Program Files/Cloudflare/Cloudflare WARP/:/mnt/c/Program Files/Python/Python311/Scripts/:/mnt/c/Program Files/Python/Python311/:/mnt/c/Users/Amen/AppData/Local/Microsoft/WindowsApps:/mnt/c/Program Files/Microsoft VS Code/bin:/snap/bin
amensaywho@CONSOLE:~/ROOT_Tutorial$ echo $LD_LIBRARY_PATH
/home/amensaywho/geant4/geant4-v11.2.2-install/lib:/home/amensaywho/root/lib

Related question: running another macro, given below, returns the error: Error in <TTree::Branch>: The class requested (vector<MyEvent>) for the branch "Events" is an instance of an stl collection and does not have a compiled CollectionProxy. Please generate the dictionary for this collection (vector<MyEvent>) to avoid to write corrupted data.

tree_example10.C:

//Tree with vector<MyEvent> as branch
#include <vector>
#include "MyEvent.h"

void tree_example10() {

  TFile *f = new TFile("myfile_example10.root", "RECREATE");
  TTree *T = new TTree("T","tree with vector");
  TRandom r;
  std::vector<MyEvent> *events = new std::vector<MyEvent>();

  T->Branch("Events", "std::vector<MyEvent>", &events);

  for (Int_t i = 0; i < 1000; i++) {

    //clean vectors for each event
    events->clear();
    //Fill vectors for each event
    Float_t px, py;
    Int_t np = (Int_t)(r.Rndm()*10);
    for(Int_t j = 0; j < np; j++){
      r.Rannor(px, py);
      Float_t pt = std::sqrt(px*px + py*py);
      MyEvent event;
      event.setPx(px);
      event.setPy(py);
      event.setPt(pt);
      events->push_back(event);
    }
    T->Fill();
  }
  
  f->Write();
  f->Close();

  delete events;
}

The header file for MyEvent.h is same as above. How do I resolve this? Would be great if someone could explain the error as well

It all look consistent, so I am not sure why you are seeing this problem :(.

Related question: running another macro, given below, returns the error: Error in <TTree::Branch>: The class requested (vector<MyEvent>) for the branch "Events" is an instance of an stl collection and does not have a compiled CollectionProxy. Please generate the dictionary for this collection (vector<MyEvent>) to avoid to write corrupted data.

When storing a ‘standalone’ vector you need to explicitly request the dictionary for it.
Add to your MyEvent.h:

#ifdef __ROOTCLING__
#pragma link C++ class std::vector<MyEvent>+;
#endif

I understand, no problem and thank you :slight_smile:

Huh, so I have to add said lines for every Event Class I define (if i want to use said class in a vector)? Are there ways where I don’t have to explicitly request the dictionary for the vector?

Yes. When you use the syntax .L ...+ one of the implicit operation is to add the equivalent of the pragma link line for the classes declared in the the file. In addition when generating the dictionary for a class, the system will also automatically generate the dictionary for any collection it uses. So if you add to your MyEvent.h the class:

class EventHolder {
    std::vector<Event> f1;
    std::list<Event> f2;
};

the dictionaries for std::vector<Event> and std::list<Event> will be automatically generated.

1 Like