/***************************************************************************** * Project: RooFit * * Package: RooFitCore * * File: $Id: RooArgList.h,v 1.14 2007/05/11 09:11:30 verkerke Exp $ * Authors: * * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu * * DK, David Kirkby, UC Irvine, dkirkby@uci.edu * * * * Copyright (c) 2000-2005, Regents of the University of California * * and Stanford University. All rights reserved. * * * * Redistribution and use in source and binary forms, * * with or without modification, are permitted according to the terms * * listed in LICENSE (http://roofit.sourceforge.net/license.txt) * *****************************************************************************/ #ifndef ROO_ARG_LIST #define ROO_ARG_LIST #include "RooAbsCollection.h" class RooArgList : public RooAbsCollection { public: // Constructors, assignment etc. RooArgList(); RooArgList(const RooAbsCollection& coll) ; explicit RooArgList(const TCollection& tcoll, const char* name="") ; explicit RooArgList(const char *name); /// Construct a (non-owning) RooArgList from one or more /// RooFit objects. /// \param arg A RooFit object to be put in the set. /// Note that you can also pass a `double` as first argument /// when constructing a RooArgList, and another templated /// constructor will be used where a RooConstVar is implicitly /// created from the `double` value. /// \param moreArgsOrName Arbitrary number of /// - RooFit objects deriving from RooAbsArg. /// - `double`s from which a RooConstVar is implicitly created via `RooFit::RooConst`. /// - A c-string to name the set. template RooArgList(RooAbsArg const& arg, Args_t &&... moreArgsOrName) /*NB: Making this a delegating constructor led to linker errors with MSVC*/ { // This constructor should cause a failed static_assert if any of the input // arguments is a temporary (r-value reference), which will be checked in // processArg. This works statically because of the universal reference // mechanism with templated functions. // Unfortunately, we can't check the first arg, because it's type can't be // a template parameter and hence a universal reference can't be used. // This problem is solved by introducing another templated constructor below, // which accepts a RooAbsArg && as the first argument which is forwarded to // be the second argument for this constructor. processArgs(arg, std::forward(moreArgsOrName)...); } /// This constructor will provoke a `static_assert`, because passing a /// RooAbsArg as r-value reference is not allowed. template RooArgList(RooAbsArg && arg, Args_t &&... moreArgsOrName) : RooArgList{arg, std::move(arg), std::forward(moreArgsOrName)...} {} template explicit RooArgList(double arg, Args_t &&... moreArgsOrName) { processArgs(arg, std::forward(moreArgsOrName)...); } /// Construct from iterators. /// \tparam Iterator_t An iterator pointing to RooFit objects or pointers/references thereof. /// \param beginIt Iterator to first element to add. /// \param endIt Iterator to end of range to be added. /// \param name Optional name of the collection. template::value_type>, typename = std::enable_if::value> > RooArgList(Iterator_t beginIt, Iterator_t endIt, const char* name="") : RooArgList(name) { for (auto it = beginIt; it != endIt; ++it) { processArg(*it); } } /// Construct a non-owning RooArgList from a vector of RooAbsArg pointers. /// This constructor is mainly intended for pyROOT. With cppyy, a Python list /// or tuple can be implicitly converted to an std::vector, and by enabling /// implicit construction of a RooArgList from a std::vector, we indirectly /// enable implicit conversion from a Python list/tuple to RooArgLists. /// \param vec A vector with pointers to the arguments or doubles for RooFit::RooConst(). RooArgList(std::vector const& vec) { for(auto const& arg : vec) { if(arg.hasPtr) processArg(arg.ptr); else processArg(arg.val); } } ~RooArgList() override; // Create a copy of an existing list. New variables cannot be added // to a copied list. The variables in the copied list are independent // of the original variables. RooArgList(const RooArgList& other, const char *name=""); /// Move constructor. RooArgList(RooArgList && other) : RooAbsCollection(std::move(other)) {} TObject* clone(const char* newname) const override { return new RooArgList(*this,newname); } TObject* create(const char* newname) const override { return new RooArgList(newname); } RooArgList& operator=(const RooArgList& other) { RooAbsCollection::operator=(other) ; return *this ; } /// Return object at given index, or nullptr if index is out of range inline RooAbsArg* at(Int_t idx) const { if (idx >= static_cast(_list.size())) return nullptr; return _list[idx]; } // I/O streaming interface (machine readable) virtual bool readFromStream(std::istream& is, bool compact, bool verbose=false); virtual void writeToStream(std::ostream& os, bool compact); /// Access element by index. RooAbsArg& operator[](Int_t idx) const { assert(0 <= idx && idx < static_cast(_list.size())); return *_list[idx]; } protected: bool canBeAdded(RooAbsArg const&, bool) const override { return true; } private: template void processArgs(Args_t &&... args) { // Expand parameter pack in C++ 11 way: int dummy[] = { 0, (processArg(std::forward(args)), 0) ... }; (void)dummy; } void processArg(const RooAbsArg& arg) { add(arg); } void processArg(const RooAbsArg* arg) { add(*arg); } void processArg(RooAbsArg* arg) { add(*arg); } template void processArg(Arg_t && arg) { assert_is_no_temporary(std::forward(arg)); add(arg); } void processArg(const char* name) { _name = name; } void processArg(double value); ClassDefOverride(RooArgList,1) // Ordered list of RooAbsArg objects }; namespace RooFitShortHand { template RooArgList L(Args_t&&... args) { return {std::forward(args)...}; } } // namespace RooFitShortHand #endif