How to check if a class is streamable

I used to check if a class can be streamed to a Root file like this:

if (tClass && tClass->IsLoaded() && tClass->HasDictionary())

but I just realized that for some classes, e.g. std::array<TH1F, N>, the tClass->HasDictionary() statement can be false but nevertheless it can be correctly streamed to a Root file.
So what is the most general way to check if a class can be written to file?

Hi Nicola,

ROOT can cope with some cases where the dictionary is not present, for example for containers that have a storage guaranteed to be contiguous in memory.
Nevertheless, it is very good practice, e.g. for future data model evolution, to always use dictionaries. The condition you have in your post is excellent for that, even if I believe TClass::HasDictionary() is really the key method.

Best,
D

Hi Danilo,

doing as you suggest would make it impossible to save e.g. a std::array<TCanvas,6>: it has no dictionary so the check will fail:

root [17] TClass::GetClass("std::array<TCanvas,6>")->HasDictionary()
(bool) false

but if I try to build a dictionary for it then rootcling fails as well with:

Error: It is not necessary to explicitly select class array<TCanvas,6>. I/O is supported for it transparently.

So how can I solve this?

Edit: to be clear, I perform the check before writing to file with TFile::WriteObjectAny, that’s why I say that a failing check would make it impossible to write to file.

Hi Nicola,

std::arrays are treated as C arrays. Unfortunately this is why you ended up in this situation.
Would it be possible to use std::vector<TCanvas> instead?

Best,
D

Yes of course, but since I’m writing generic code that in principle handles any kind of class I would like to let my users stream std::arrays if they need/wish so.

What about this?

// Retrieve object class and put in tClass, then:
if (tClass){
  if (file->WriteObjectAny(objPtr, tClass, objName) == 0){
    std::cerr << "Error: can't save object to file" << std::endl;
  } else {
    std::cout << "Object saved to file" << std::endl;
  }

The documentation for TDirectoryFile::WriteObjectAny lacks information about the return value so I’m not sure.

You code is correct except for a few cases including: std::pair, std::tuple, std::array, std::unique_ptr.
You could ‘hard code’ that those are streamable. or you can use TClass::GetMissingDictionaries(THashTable& result, bool recurse = false);

Hi Philippe,

I guess you are you referring to the code in my first post, right?

Yes, GetMissingDictionary was about the original post.

WriteObjectAny returns the number of bytes written. So indeed a return value of zero would indicates that something went wrong: this includes the file being read-only or any missing information about the class.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.