I’m working on some code that requires a couple of TTreeReaderValue<T> Variables to be declared before they’re defined, it works well in ROOT 6.10. But now working with ROOT 6.13 (just built) I found this error all over the place:
error: call to deleted constructor of 'TTreeReaderValue<Int_t>' (aka 'TTreeReaderValue<int>')
and:
note: 'TTreeReaderValue' has been explicitly marked deleted here
TTreeReaderValue() = delete;
This change was introduced here. Is there any way around it? You can get the same error by trying to declare a variable like:
I will have to re-visit that, thanks for pointing it out. I don’t remember from the top of my head why I deleted the default constructor.
As a workaround you can use unique_ptr<TTreeReaderValue<Int_t>>, and create it (e.g. using std::make_unique from ROOT/RMakeUnique.hxx) when you currently set the tree and branch name.
Hi,
isn’t a default-constructed TTreeReaderValue completely useless? It has no setters afaik, so you cannot default-construct it and later make it point to the right TTreeReader and branch.
@amvargash I am curious what the use-case is for default-constructing TTreeReaderValues.
I am not sure what you mean with “variables are declared before they are defined” – in C++ forward declaration of variables is expressed with the extern keyword, but that does not trigger a default construction. If you don’t put extern in front of the declaration that counts as definition.
MPr::Mpr(/* not the default constructor */)
: fn(fReader, "P.tr.n1"),
fn(fReader, "P.tr.n2")
{
.....
}
....
I think I saw a similar example when using TSelector for TProof but I don’t remember right now where (and I use them here for a different purpose than TProof).
EDIT: The constructor shown is not the default constructor.
Hi @behrenhoff, as I mentioned initially, you can get the same error by runing:
root[0] TTreeReaderValue<Int_t> n
And then you get:
ROOT_prompt_0:1:25: error: call to deleted constructor of 'TTreeReaderValue<Int_t>' (aka 'TTreeReaderValue<int>')
TTreeReaderValue<Int_t> n
^
$ROOTSYS/include/TTreeReaderValue.h:130:4: note: 'TTreeReaderValue' has been explicitly marked deleted here
TTreeReaderValue() = delete;
Hi,
I think there are some pieces missing in your explanation:
TTreeReaderValues cannot be default-constructed (anymore), but that is a good thing, because a default-constructed TTreeReaderValue is effectively useless.
On the other hand, your code snippet does not default-construct any TTreeReaderValue (root[0] TTreeReaderValue<Int_t> n does, but that’s not your case).
It would be good to find out what is the exact piece of C++ code that you are compiling that is trying to default-construct a TTreeReaderValue, and why: it’s probably not what you want.
Hi @eguiraud. The error is originated in the default constructor of the class. Look, this is the very first line that it shows when trying to use a Script that uses MPr
MPr.cxx:6:9: error: call to deleted constructor of 'TTreeReaderValue<TTimeStamp>'
MPr::MPr(){
^
Alright, so the default ctor of MPr default-constructs some TTreeReaderValues.
Independently of @Axel deciding to reinstate the default ctor or not, default TTreeReaderValues are useless (I guess you never actually use them, as they can do nothing), so you might want to avoid constructing them altogether.
One way to do so is changing the types of your data members from TTreeReaderValue<TTimeStamp> to std::unique_ptr<TTreeReaderValue<TTimeStamp>>, as @Axel suggested above. Or maybe revisit the logic of MPr (what does a default-constructed MPrmean? It certainly is a different object than a non-default-constructed MPr, because it has less capabilities: it will never read any data with a TTreeReaderValue).
Yes, but what is that default constructor good for? You can’t use the object anyway. So why do you need to be able to default-construct MPr - its internal TTreeReaders seem useless in that case.
So maybe it falls back to a SW design question?
(and my prev comment “And how does this code require a default constructible TTreeReaderValue?” was of course a direct answer to the code you were showing - there was no TTreeReaderValue default constructor involved in your snippet)
Right after, it also solves the problem. If I’m not wrong the default constructor is required somewhere (I’ll check).
I was thinking the lines in the header were related with the error produced, but @eguiraud made me realize the error was coming from another piece of code .
(if I don’t use it I get the “call to deleted…”) . I was trying to define a Set method in the same way TDatime use it (https://github.com/root-project/root/blob/f32175eb0b4da1b95180f029efe2064d90c93b0e/core/base/src/TDatime.cxx#L58) in order to avoid writing the same code again and again (just don’t look like the right way to do it) However I can’t use that portion of the code in another member which is not a constructor. Do you know any other way to avoid writing these definitions more than once?
In C++, when the body of constructors is executed, all data members have already been constructed. This means that you cannot construct your TTreeReaderValues inside a Set method that you would call from the ctor body (they have already been constructed, or better you already tried to invoke their deleted default constructor).
What you probably want is delegating constructors, i.e. you probably want to call one constructor from the others to avoid code repetition.