root
root copied to clipboard
Error when copying a tuple into a specific position of a vector of tuples in PyROOT
Describe the bug
Insertion of a tuple into a vector seems to be buggy on the Python side
>>> import ROOT
>>> a = ROOT.std.vector('tuple<long, long, double, double>')(2)
>>> b = ROOT.std.make_tuple[ROOT.long, ROOT.long, ROOT.double, ROOT.double](1, 2, 3, 4)
>>> a[0] = b
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: tuple<long,long,double,double>& std::vector<tuple<long,long,double,double> >::operator[](unsigned long __n) =>
TypeError: none of the 2 overloaded methods succeeded. Full details:
ROOT::Internal::TEmulatedTuple<long,long,double,double>& tuple<long,long,double,double>::operator=(ROOT::Internal::TEmulatedTuple<long,long,double,double>&&) =>
ValueError: could not convert argument 1 (object is not an rvalue)
ROOT::Internal::TEmulatedTuple<long,long,double,double>& tuple<long,long,double,double>::operator=(const ROOT::Internal::TEmulatedTuple<long,long,double,double>&) =>
TypeError: could not convert argument 1
While this works at the prompt
root [0] std::vector<std::tuple<long,long,double,double>> myvec{2};
root [1] std::tuple<long,long,double,double> myt{1,2,3,4};
root [2] myvec[0] = myt;
I couldn't understand how to reproduce the issue with TEmulatedTuple
which is defined internally in TCling starting at https://github.com/root-project/root/blob/de302abeae86368724e69a7a0e7a24b2dff28f07/core/metacling/src/TCling.cxx#L3876
Expected behavior
Insertion of a tuple into a vector of tuples should work in PyROOT.
Setup
conda environment with ROOT 6.24/02 on Fedora32
Additional context
First reported on the forum at https://root-forum.cern.ch/t/using-std-tuple-in-pyroot/46347/3
It seems that std::tuple
is being replaced by ROOT::Internal::TEmulatedTuple
. The same error can be reproduced with:
>>> b = ROOT.std.make_tuple[ROOT.int](1)
>>> c = ROOT.std.make_tuple[ROOT.int](1)
>>> b.__assign__(c)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: none of the 2 overloaded methods succeeded. Full details:
ROOT::Internal::TEmulatedTuple<int>& tuple<int>::operator=(ROOT::Internal::TEmulatedTuple<int>&&) =>
ValueError: could not convert argument 1 (object is not an rvalue)
ROOT::Internal::TEmulatedTuple<int>& tuple<int>::operator=(const ROOT::Internal::TEmulatedTuple<int>&) =>
TypeError: could not convert argument 1
This looks like a nasty mix of runtime reflection information and IO (we use TEmulatedTuple to abstract from implementation details of the tuple class in the stl to perform IO in a simple way). @pcanal would you be able to suggest a path to improve the current situation?
The problem seems to be on the PyROOT side. If you do this:
c = a[1]
c = b
everything works. Can it be linked to the fact that operator[] returns a reference?