Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RF] New RooStringView class for passing std::strings to functions #9747

Merged
merged 4 commits into from
Jan 29, 2022

Conversation

guitargeek
Copy link
Contributor

@guitargeek guitargeek commented Jan 28, 2022

A new RooStringView is introduced as a copy-free drop-in replacement for const char* in public RooFit interfaces, which also accepts a std::string.

So far, this new RooStringView is used in the RooWorkspace accessors, and also in the dataset classes as it's a superior solution over using std::string view, which is not guaranteed to be null-terminated and needs specific preprocessor macros for the C++ case.

Many RooFit function take a C-style string `const char*` as an argument.
This commit proposes a mechanism to generalize such interfaces to also
accepts `std::string`.

Two options would have been the following, but they both have drawbacks:

 1. Use `std::string const&` directly. Problem: the C-style string is
    copied implicitly to create the `std::string`.
 3. Use `std::string_view`. Problem: a `std::string_view` is not
    necessarily null-terminated, to converting it to a C-style string
    involves again a copy.

The alternative copy-fee solution that this commit suggests is a C-style
string wrapper called `RooStringView`, that can be implicitely
constructed from a `std::string` as well. Like this, there will be no
memory reallocation/copying when one passes a `const char*`.

The New RooStringView is used in this commit for the first time to
generalize the RooWorkspace accessor functions to also accept
`std::string`.
Some code modernization, where we profit from the new possibility to
pass `std::string` directly to the RooWorkspace accessor functions
thanks to the `RooStringView`.
This has two advantages over `std::string_view`:

 1. We don't need preporcessor macros and branches to support ROOT's
    std::string_view backport for C++14.
 2. The `std::string_view` was not appropriate anyway, because in the
    `TNamed` constructor the strig had to be copied anyway to guarantee
    the string is null-terminated. With `RooStringView` we don't have
    this problem: it is guaranteed to be null-terminated.
The RooDataHist has two similar constructors:

```C++
RooDataHist(RooStringView name, RooStringView title, const RooArgSet& vars, const char* binningName);
RooDataHist(RooStringView name, RooStringView title, const RooArgList& vars, const RooCmdArg& arg1);
```

The problem: a `RooCmdArg` can be implicitly constructed from a `const
char*`. Therefore, if one doesn't explicitly choose one of the two
overloads by passing a RooArgSet or RooArgList as the third argument
explicitly, both overloads are succeeding in PyROOT. Unlike in C++,
the overload that doesn't require implicit conversion is not
prioritized.

Here is an example of where this goes wrong:

```Python
ROOT.RooDataHist(name, title, variables, "my_binning")
```

...causing...

```
[#0] ERROR:InputArguments -- RooDataHist::ctor() ERROR: unrecognized command: my_binning
```

...because the constructor with the RooCmdArg is used.

It was sheer luck that this problem didn't appear so far. It only
appeared after the the constructors were changed to use `RooStringView`,
probably because the order is which the overloads are tried is not well
defined.

The solution: make the implicit construction of `RooCmdArg` from just a
string impossible. This is done by requiring at least one non-default
payload parameter. This is not breaking any code, because constructing a
RooCmdArg without any payload doesn't make sense anyway.
@phsft-bot
Copy link
Collaborator

Starting build on ROOT-debian10-i386/cxx14, ROOT-performance-centos8-multicore/default, ROOT-ubuntu16/nortcxxmod, ROOT-ubuntu2004/soversion, mac1015/python3, mac11/cxx17, windows10/cxx14
How to customize builds

Copy link
Member

@lmoneta lmoneta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks fine.
It is true it simplifies now a lot of code using the Workspace. The only concern I have by doing this is a bloat of the interfaces. Should we do these for all RooFit classes ? And maybe also other ROOT classes ?

inline RooArgSet argSet(std::string const& nameList) const { return argSet(nameList.c_str()); }
inline TObject* genobj(std::string const& name) const { return genobj(name.c_str()); }
inline TObject* obj(std::string const& name) const { return obj(name.c_str()); }

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need these extra functions ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am referring here to componentIterator and components

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know where they are used exactly, but they were there before so I would suggest to not remove them from the interface

@phsft-bot
Copy link
Collaborator

Build failed on mac11/cxx17.
Running on macphsft23.dyndns.cern.ch:/Users/sftnight/build/workspace/root-pullrequests-build
See console output.

Warnings:

  • [2022-01-28T17:27:47.871Z] /Library/Developer/CommandLineTools/SDKs/MacOSX11.3.sdk/usr/include/c++/v1/memory:2084:5: warning: delete called on 'RooFit::Experimental::JSONNode::child_iterator_t<RooFit::Experimental::JSONNode>::Impl' that is abstract but has non-virtual destructor [-Wdelete-abstract-non-virtual-dtor]
  • [2022-01-28T17:27:47.871Z] /Library/Developer/CommandLineTools/SDKs/MacOSX11.3.sdk/usr/include/c++/v1/memory:2084:5: warning: delete called on 'RooFit::Experimental::JSONNode::child_iterator_t<const RooFit::Experimental::JSONNode>::Impl' that is abstract but has non-virtual destructor [-Wdelete-abstract-non-virtual-dtor]
  • [2022-01-28T17:27:47.871Z] /Library/Developer/CommandLineTools/SDKs/MacOSX11.3.sdk/usr/include/c++/v1/memory:2084:5: warning: delete called on non-final '(anonymous namespace)::childItImpl<RooFit::Experimental::JSONNode>' that has virtual functions but non-virtual destructor [-Wdelete-non-abstract-non-virtual-dtor]
  • [2022-01-28T17:27:47.871Z] /Library/Developer/CommandLineTools/SDKs/MacOSX11.3.sdk/usr/include/c++/v1/memory:2084:5: warning: delete called on non-final '(anonymous namespace)::childItImpl<const RooFit::Experimental::JSONNode>' that has virtual functions but non-virtual destructor [-Wdelete-non-abstract-non-virtual-dtor]
  • [2022-01-28T17:27:51.009Z] /Library/Developer/CommandLineTools/SDKs/MacOSX11.3.sdk/usr/include/c++/v1/memory:2084:5: warning: delete called on 'RooFit::Experimental::JSONNode::child_iterator_t<const RooFit::Experimental::JSONNode>::Impl' that is abstract but has non-virtual destructor [-Wdelete-abstract-non-virtual-dtor]
  • [2022-01-28T17:27:51.009Z] /Library/Developer/CommandLineTools/SDKs/MacOSX11.3.sdk/usr/include/c++/v1/memory:2084:5: warning: delete called on 'RooFit::Experimental::JSONNode::child_iterator_t<const RooFit::Experimental::JSONNode>::Impl' that is abstract but has non-virtual destructor [-Wdelete-abstract-non-virtual-dtor]
  • [2022-01-28T17:27:51.009Z] /Library/Developer/CommandLineTools/SDKs/MacOSX11.3.sdk/usr/include/c++/v1/memory:2084:5: warning: delete called on non-final 'TJSONTree::Node::childItImpl<RooFit::Experimental::JSONNode, TJSONTree::Node, nlohmann::detail::iter_impl<nlohmann::basic_json<>>>' that has virtual functions but non-virtual destructor [-Wdelete-non-abstract-non-virtual-dtor]
  • [2022-01-28T17:27:51.010Z] /Library/Developer/CommandLineTools/SDKs/MacOSX11.3.sdk/usr/include/c++/v1/memory:2084:5: warning: delete called on 'RooFit::Experimental::JSONNode::child_iterator_t<RooFit::Experimental::JSONNode>::Impl' that is abstract but has non-virtual destructor [-Wdelete-abstract-non-virtual-dtor]
  • [2022-01-28T17:27:51.010Z] /Library/Developer/CommandLineTools/SDKs/MacOSX11.3.sdk/usr/include/c++/v1/memory:2084:5: warning: delete called on non-final 'TJSONTree::Node::childItImpl<const RooFit::Experimental::JSONNode, const TJSONTree::Node, nlohmann::detail::iter_impl<const nlohmann::basic_json<>>>' that has virtual functions but non-virtual destructor [-Wdelete-non-abstract-non-virtual-dtor]
  • [2022-01-28T17:27:51.010Z] /Library/Developer/CommandLineTools/SDKs/MacOSX11.3.sdk/usr/include/c++/v1/memory:2084:5: warning: delete called on 'RooFit::Experimental::JSONNode::child_iterator_t<const RooFit::Experimental::JSONNode>::Impl' that is abstract but has non-virtual destructor [-Wdelete-abstract-non-virtual-dtor]

And 1 more

Failing tests:

@phsft-bot
Copy link
Collaborator

Starting build on ROOT-debian10-i386/cxx14, ROOT-performance-centos8-multicore/default, ROOT-ubuntu16/nortcxxmod, ROOT-ubuntu2004/soversion, mac1015/python3, mac11/cxx17, windows10/cxx14
How to customize builds

@guitargeek guitargeek changed the title [RF] Add std::string overloads for RooWorkspace accessor functions [RF] New RooStringView class for passing std::strings to functions Jan 28, 2022
@phsft-bot
Copy link
Collaborator

@phsft-bot
Copy link
Collaborator

Build failed on ROOT-debian10-i386/cxx14.
Running on pcepsft10.dyndns.cern.ch:/build/workspace/root-pullrequests-build
See console output.

Failing tests:

@phsft-bot
Copy link
Collaborator

Build failed on ROOT-ubuntu2004/soversion.
Running on root-ubuntu-2004-1.cern.ch:/home/sftnight/build/workspace/root-pullrequests-build
See console output.

Failing tests:

@phsft-bot
Copy link
Collaborator

Build failed on ROOT-ubuntu16/nortcxxmod.
Running on sft-ubuntu-1604-1.cern.ch:/build/workspace/root-pullrequests-build
See console output.

Failing tests:

@phsft-bot
Copy link
Collaborator

@phsft-bot
Copy link
Collaborator

Build failed on mac1015/python3.
Running on macitois19.dyndns.cern.ch:/Users/sftnight/build/workspace/root-pullrequests-build
See console output.

Failing tests:

@phsft-bot
Copy link
Collaborator

Starting build on ROOT-debian10-i386/cxx14, ROOT-performance-centos8-multicore/default, ROOT-ubuntu16/nortcxxmod, ROOT-ubuntu2004/soversion, mac1015/python3, mac11/cxx17, windows10/cxx14
How to customize builds

@phsft-bot
Copy link
Collaborator

Build failed on ROOT-performance-centos8-multicore/default.
Running on olbdw-01.cern.ch:/data/sftnight/workspace/root-pullrequests-build
See console output.

Failing tests:

@guitargeek
Copy link
Contributor Author

Hi @lmoneta, thanks for the review! You are right, it's not a sustainable solution to duplicate the interfaces if we want to accept std::string more generally in RooFit. I have updated the PR with a new intermediate class that can be used for the interfaces. The intermediate class, RooStringView, is simply a wrapper around const char* that can also be constructed from a std::string. Note that this is different from std::string_view, which is not null-terminated and therefore needs a copy when turned into a const char*, so we couldn't use that in RooFit interfaces without introducing superfluous copies.

@guitargeek guitargeek merged commit b553d38 into root-project:master Jan 29, 2022
@guitargeek guitargeek deleted the rooworkspace_1 branch January 29, 2022 23:43
@smuzaffar
Copy link
Contributor

@guitargeek , I am trying to test the latest root master changes and notice that cmssw code https://github.com/cms-sw/cmssw/blob/master/PhysicsTools/Utilities/src/SideBandSubtraction.cc#L415 fails due to this change. Should I update cmssw to use something like the following now?

fit_result = ModelPDF->fitTo(*Data, RooCmdArg("r", 0));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants