Home | News | Documentation | Download

Warning in <MyClass>: The data members of MyClass will not be stored, because it inherits from TObject but does not have its own ClassDef

Hello,
in a standalone CMake project with ROOT integration, I get several of this type of compilation warnings from “metacling” for some derived classes that I create:

Warning in <MyClass>: The data members of MyClass will not be stored, because it inherits from TObject but does not have its own ClassDef.

I believe it happens when calling ROOT_GENERATE_DICTIONARY(…) CMake macro.

I would prefer not to define a ClassDef for these classes. Is there an empty ‘ClassDef’ macro or compilation flag / verbosity level to disable this warning explicitly, so that I do not get the command line filled with it, which makes it harder to find the real warnings?

Thanks in advance for the help!


ROOT Version: 6.23/01
Platform: Ubuntu 18
Compiler: gcc, cmake


Hello,

You can set gErrorIgnoreLevel = kWarning, but that will disable all ROOT warnings (edit: if the warning happens when calling ROOT_GENERATE_DICTIONARY, then what I suggested won’t help).

Regarding ClassDef, perhaps @Axel can answer.

Thanks for the reply. I tried adding this, but it did not work, because the error appears when compiling, not when running.

which makes it harder to find the real warnings?

If you class inherits from TObject AND you do not use a ClassDef then the data in those classes will not be saved (because the system relies on the overload of functions implemented in the linkdef, eg, IsA and `Streamer).

I.e. It is a REAL warning and actually in almost all cases an error.

Why do you prefer to not define a ClassDef? What is the advantage for you?

Why do you inherit from TObject?

Cheers,
Philippe.

Thanks for the reply.

It is a GUI window, thus I do not want to save it or stream it.

class MainWindow : public TGMainFrame

In principle, I would have no problem of adding the ClassDef even if I do not need it. But the problem is that, if I add it, I am not able to use forward declaration in my header.

I use now:

class TGCheckButton;
class TGComboBox;
class TGLabel;
class TGHProgressBar;
class TGSpeedo;
class TGHtml;
class TGTab;
class TGToolBar;

(...)

private:
    TGTab* myTab{};
    TGTextButton* myButton{};
(...)

Without ClassDef, all works fine except for the metacling warning.
With the ClassDef, that fails to compile, with the error:

Error in <CheckDefinition>: Missing definition for class TGTab, please #include its header in the header of MainWindow
In file included from input_line_8:3:
In file included from MainWindow.hpp:9:
/opt/root_bld/include/TGFrame.h:34:7: error: incomplete type 'TGTextButton' where a complete type is required

Thus, I prefer to keep my headers cleaner without extra includes and ClassDefs.

I think you can add those “missing” headers in the LinkDef file as:

#pragma link extra_include "TGTextButton.h"

(or maybe directly as #include)

Hmmm, but I do not have any LinkDef file in my CMake project.

As I just wanted a minimal GUI class deriving from TGMainFrame, I call the ROOT_GENERATE_DICTIONARY without using the LINKDEF argument, as done here:

Or is it a bad practice not to specify a LinkDef?

Well having a LinkDef let you control more carefully what the dictionary does and would give you an opportunity to suppress the warnings.

Alternatively you could try a relatively new alternative (so you mileage may vary) and remove the dictionary generation altogether and add a ClassDefInline macro (instead of the ClassDef macro).
If it works in you case, it will simply your build while still letting you use forward declaration.

Cheers,
Philippe.

Thanks for the tip, that inline solution works really great for me. No warnings when compiling, no warnings when running. And I do no need any more the extra hacks that I had added in my CMakeLists to suppress warnings, see Silence GCC warnings in CMake C++ standalone project with ROOT classes and dictionaries .

The only downside is that I have to add in my main.cpp file all the paths that are in my CMakeLists, hard-coding them by hand, as the files I want to #include depend on them:
(which I did not need to do before when I generated the explicit dictionaries as CMake was taking care of all of it)

    gInterpreter->AddIncludePath("myprogram/submodule1/");
    gInterpreter->AddIncludePath("myprogram/core/");
    gInterpreter->AddIncludePath("/opt/boost/...");
    gInterpreter->AddIncludePath("/opt/mydriver/api");
    gInterpreter->Declare("#include \"MainWindow.hpp\"");//MainWindow.hpp includes headers that are located in the places above
    MainWindow window(...);

Or is there a more automated way of passing to TInterpreter the same include-paths as used in the CMakeLists.txt ?

Thanks for the awesome support.

Or is there a more automated way of passing to TInterpreter the same include-paths as used in the CMakeLists.txt ?

I am afraid that on our side the way to do it is to generate a dictionary … :wink:

On your side, you could create a custom target that generate a (source or header) file that contains the information.

Cheers,
Philippe.

1 Like