Loading [MathJax]/extensions/tex2jax.js
Go to the documentation of this file.
11 #ifndef FUNCTIONAL_DETAILS_H
12 #define FUNCTIONAL_DETAILS_H
17 #include <type_traits>
29 #include <range/v3/version.hpp>
30 #include <range/v3/view/const.hpp>
31 #include <range/v3/view/zip.hpp>
33 #if RANGE_V3_VERSION < 900
35 using namespace ranges::view;
39 #if defined( __clang__ ) && ( __clang_major__ < 11 ) || defined( __APPLE__ ) && ( __clang_major__ < 12 )
40 # define GF_SUPPRESS_SPURIOUS_CLANG_WARNING_BEGIN \
41 _Pragma( "clang diagnostic push" ) _Pragma( "clang diagnostic ignored \"-Wunused-lambda-capture\"" )
42 # define GF_SUPPRESS_SPURIOUS_CLANG_WARNING_END _Pragma( "clang diagnostic pop" )
44 # define GF_SUPPRESS_SPURIOUS_CLANG_WARNING_BEGIN
45 # define GF_SUPPRESS_SPURIOUS_CLANG_WARNING_END
50 #define GAUDI_FUNCTIONAL_CONSTRUCTOR_USES_TUPLE
58 template <
typename OS,
typename Arg>
64 template <
typename OS,
typename Arg,
typename... Args>
78 template <
typename A,
typename B>
80 return a.size() == b.size();
84 template <
typename A,
typename B,
typename... C>
85 inline bool check_sizes(
const A& a,
const B& b,
const C&...
c ) noexcept {
90 template <
typename... Args>
94 mess <<
"Zipped containers have different sizes : ";
101 template <
typename... Args>
106 return ranges::views::zip( std::forward<Args>(
args )... );
110 template <
typename... Args>
115 return ranges::views::const_( ranges::views::zip( std::forward<Args>(
args )... ) );
123 [](
const std::string& i ) { return DataObjID{ i }; } );
129 template <
typename T>
130 using is_optional_ = decltype( std::declval<T>().has_value(), std::declval<T>().value() );
132 template <
typename T>
136 template <
typename Arg>
137 constexpr
bool is_optional_v = Gaudi::cpp17::is_detected_v<details2::is_optional_, Arg>;
139 template <
typename Arg>
142 template <
typename Arg>
145 template <
typename T>
150 template <
typename F,
typename Arg,
typename = require_is_not_optional<Arg>>
151 decltype(
auto ) operator()( F&& f, Arg&& arg )
const {
152 return std::invoke( std::forward<F>( f ), std::forward<Arg>( arg ) );
154 template <
typename F,
typename Arg,
typename = require_is_optional<Arg>>
156 if ( arg ) std::invoke( std::forward<F>( f ), *std::forward<Arg>( arg ) );
166 template <
typename Value, auto N>
167 using RepeatValues_ = decltype( get_values_helper<Value>( std::make_index_sequence<N>() ) );
171 template <
typename Out1,
typename Out2,
172 typename = std::enable_if_t<std::is_constructible_v<Out1, Out2> && std::is_base_of_v<DataObject, Out1>>>
174 return out_handle.
put( std::make_unique<Out1>( std::forward<Out2>(
out ) ) );
177 template <
typename Out1,
typename Out2,
typename = std::enable_if_t<std::is_constructible_v<Out1, Out2>>>
179 return out_handle.put( std::forward<Out2>(
out ) );
183 template <
typename OutHandle,
typename OptOut,
typename = require_is_optional<OptOut>>
184 void put(
const OutHandle& out_handle, OptOut&&
out ) {
185 if (
out )
put( out_handle, *std::forward<OptOut>(
out ) );
195 template <
typename Container>
198 template <
typename Container,
typename Value>
199 auto operator()( Container&
c, Value&&
v )
const -> decltype(
c.push_back(
v ) ) {
200 return c.push_back( std::forward<Value>(
v ) );
203 template <
typename Container,
typename Value>
205 return c.insert( std::forward<Value>(
v ) );
209 template <
typename Container,
typename Value,
210 typename = std::enable_if_t<std::is_pointer_v<typename Container::value_type>>,
211 typename = std::enable_if_t<std::is_convertible_v<Value, c_remove_ptr_t<Container>>>>
221 template <
typename In,
typename = std::enable_if_t<!std::is_po
inter_v<In>>>
226 template <
typename In,
typename = std::enable_if_t<!std::is_po
inter_v<std::decay_t<In>>>>
228 return std::forward<In>( in );
231 template <
typename In>
233 assert( in !=
nullptr );
241 template <
typename T>
244 template <
typename T,
typename IT>
247 template <
typename T,
typename IT>
250 template <
typename T>
253 template <
typename Container,
typename Value>
257 template <
typename Container,
typename Value>
262 template <
typename In>
264 template <
template <
typename>
class Handle,
typename I,
typename = std::enable_if_t<std::is_convertible_v<I, In>>>
268 template <
template <
typename>
class Handle,
typename I,
typename IT>
272 template <
template <
typename>
class Handle,
typename I,
typename IT>
276 template <
template <
typename>
class Handle,
typename I,
277 typename = std::enable_if_t<std::is_convertible_v<I*, In>>>
279 return h.getIfExists();
283 template <
typename T>
287 template <
typename T>
293 template <
typename Container>
295 static constexpr
bool is_pointer = std::is_pointer_v<Container>;
296 static constexpr
bool is_range = details2::is_gaudi_range_v<Container>;
297 using val_t = std::add_const_t<std::remove_pointer_t<Container>>;
298 using ptr_t = std::add_pointer_t<val_t>;
299 using ref_t = std::add_lvalue_reference_t<val_t>;
304 using value_type = std::conditional_t<is_pointer, ptr_t, val_t>;
307 using it_t =
typename ContainerVector::const_iterator;
311 using ret_t = std::conditional_t<is_pointer, ptr_t, ref_t>;
324 if constexpr ( is_range ) {
339 explicit operator bool()
const {
return !is_null(); }
343 template <
typename T>
346 std::bool_constant < is_pointer || is_range > {} );
352 template <
typename X = Container>
353 std::enable_if_t<!std::is_pointer_v<X>,
ref_t>
front()
const {
354 return *m_containers.
front();
356 template <
typename X = Container>
357 std::enable_if_t<std::is_pointer_v<X>,
ptr_t>
front()
const {
358 return m_containers.
front();
361 template <
typename X = Container>
362 std::enable_if_t<!std::is_pointer_v<X>,
ref_t>
back()
const {
363 return *m_containers.
back();
365 template <
typename X = Container>
366 std::enable_if_t<std::is_pointer_v<X>,
ptr_t>
back()
const {
367 return m_containers.
back();
370 template <
typename X = Container>
372 return *m_containers[i];
374 template <
typename X = Container>
376 return m_containers[i];
379 template <
typename X = Container>
381 return *m_containers[i];
383 template <
typename X = Container>
385 return m_containers[i];
393 template <
typename Tr>
395 template <
typename Tr,
typename T>
397 template <
typename Tr,
typename T>
400 template <
typename T>
401 constexpr
auto is_tool_v = std::is_base_of_v<IAlgTool, std::decay_t<T>>;
403 template <
typename T>
406 template <
typename T>
413 template <
typename Tr,
typename Base = GaudiAlgorithm>
420 template <
typename Tr,
typename T>
422 template <
typename Tr,
typename T>
425 template <
typename Traits>
427 std::is_base_of_v<Gaudi::details::LegacyAlgorithmAdapter, details::BaseClass_t<Traits>>;
430 #define GAUDI_FUNCTIONAL_MAKE_VECTOR_OF_HANDLES_USES_DATAOBJID
432 template <
typename Handles>
435 handles.reserve( init.
size() );
437 [&](
const auto& loc ) ->
typename Handles::value_type {
438 return { loc, owner };
443 template <
typename Handle,
typename Algo>
450 template <
typename IFace,
typename Algo>
452 return handle.bind(
ctx );
455 template <
typename Handle>
456 auto getKey(
const Handle&
h ) -> decltype(
h.objKey() ) {
462 template <
typename... In>
467 "EventContext can only appear as first argument" );
469 template <
typename Algorithm,
typename Handles>
475 template <
typename Algorithm,
typename Handles>
477 return std::apply( [&](
const auto&... handle ) {
return algo(
get( handle, algo,
ctx )... ); }, handles );
482 template <
typename... In>
487 "EventContext can only appear as first argument" );
489 template <
typename Algorithm,
typename Handles>
491 return std::apply( [&](
const auto&... handle ) {
return algo(
ctx,
get( handle, algo,
ctx )... ); }, handles );
494 template <
typename Algorithm,
typename Handles>
500 template <
typename... In>
503 template <
typename OutputSpec,
typename InputSpec,
typename Traits_>
506 template <
typename Out,
typename In,
typename Tr>
509 auto sc = parent.setProperty( prop, newLoc );
510 if ( sc.isFailure() )
throw GaudiException(
"Could not set Property", prop +
" -> " + newLoc, sc );
513 template <
typename Out,
typename In,
typename Tr>
518 ss <<
'[', newLocs,
", ", [](
std::ostream & os,
const auto& i ) ->
auto& {
return os <<
"'" << i <<
"'"; } )
520 auto sc = parent.setProperty( prop, ss.
str() );
521 if ( sc.isFailure() )
throw GaudiException(
"Could not set Property", prop +
" -> " + ss.
str(), sc );
524 template <
typename... Out,
typename... In,
typename Traits_>
530 const OArgs& outputs, std::index_sequence<J...> )
532 , m_inputs(
std::tuple_cat(
std::forward_as_tuple( this ),
std::
get<I>( inputs ) )... )
533 , m_outputs(
std::tuple_cat(
std::forward_as_tuple( this ),
std::
get<J>( outputs ) )... ) {
549 std::index_sequence_for<Out...>{} ) {}
565 template <std::
size_t N = 0>
566 decltype(
auto ) inputLocation()
const {
567 return getKey( std::get<N>( m_inputs ) );
569 template <
typename T>
570 decltype(
auto ) inputLocation()
const {
575 template <std::
size_t N = 0>
576 decltype(
auto ) outputLocation()
const {
577 return getKey( std::get<N>( m_outputs ) );
579 template <
typename T>
580 decltype(
auto ) outputLocation()
const {
592 template <
typename Traits_>
611 template <
typename... In,
typename Traits_>
618 , m_inputs(
std::tuple_cat(
std::forward_as_tuple( this ),
std::
get<I>( inputs ) )... ) {
637 template <std::
size_t N = 0>
638 decltype(
auto ) inputLocation()
const {
639 return getKey( std::get<N>( m_inputs ) );
641 template <
typename T>
642 decltype(
auto ) inputLocation()
const {
653 template <
typename Traits_>
660 template <
typename... Out,
typename Traits_>
667 , m_outputs(
std::tuple_cat(
std::forward_as_tuple( this ),
std::
get<J>( outputs ) )... ) {
685 template <std::
size_t N = 0>
686 decltype(
auto ) outputLocation()
const {
687 return getKey( std::get<N>( m_outputs ) );
698 template <
typename Fun,
typename Container,
typename... Args>
700 static_assert(
sizeof...( Args ) == 0,
"Args should not be used!" );
703 template <
typename Fun,
typename Container>
705 fun.postprocess(
c );
typename Tr::BaseClass BaseClass_t
auto operator()(Container &c, Value &&v) const
std::enable_if_t< std::is_pointer_v< X >, ptr_t > operator[](size_type i) const
std::enable_if_t< std::is_pointer_v< X >, ptr_t > front() const
std::add_const_t< std::remove_pointer_t< Container > > val_t
const In & operator()(const In *in) const
constexpr auto size(const T &, Args &&...) noexcept
bool PyHelper() setProperty(IInterface *p, char *name, char *value)
std::tuple< details::InputHandle_t< Traits_, In >... > m_inputs
DataHandleMixin(std::string name, ISvcLocator *locator, const KeyValue &input, const KeyValue &output)
auto get(const ToolHandle< Gaudi::Interface::Bind::IBinder< IFace >> &handle, const Algo &, const EventContext &ctx)
std::enable_if_t<!is_optional_v< Arg > > require_is_not_optional
GAUDI_API const EventContext & currentContext()
bool isReEntrant() const override
DataHandleMixin(std::string name, ISvcLocator *locator, const KeyValue &output)
Gaudi::cpp17::detected_or_t< detail2::DefaultInputHandle< T >, detail2::InputHandle_t, Tr, T > InputHandle_t
DataHandleMixin(std::string name, ISvcLocator *pSvcLocator, RepeatValues_< KeyValue, N_out > const &outputs)
constexpr struct Gaudi::Functional::details::invoke_optionally_t invoke_optionally
std::enable_if_t<!std::is_pointer_v< X >, ref_t > front() const
bool isReEntrant() const override
auto operator()(Container &c, Value &&v) const -> decltype(c.push_back(v))
DataHandleMixin(std::string name, ISvcLocator *pSvcLocator, const IArgs &inputs, std::index_sequence< I... >)
T back_inserter(T... args)
ContainerVector m_containers
auto operator()(const Handle< I > &h) -> const In &
typename it_t::iterator_category iterator_category
std::tuple< details::InputHandle_t< Traits_, In >... > m_inputs
void reserve(size_type size)
constexpr unsigned int outputLocationSize() const
bool isReEntrant() const override
typename ContainerVector::size_type size_type
decltype(auto) const_range(Args &&... args)
Zips multiple containers together to form a single const range.
DataHandleMixin(std::string name, ISvcLocator *locator, RepeatValues_< KeyValue, N_in > const &inputs, const KeyValue &output)
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
std::enable_if_t<!std::is_pointer_v< X >, ref_t > operator[](size_type i) const
friend auto operator-(const iterator &lhs, const iterator &rhs)
DataHandleMixin(std::string name, ISvcLocator *pSvcLocator, const IArgs &inputs, std::index_sequence< I... >, const OArgs &outputs, std::index_sequence< J... >)
auto get_values_helper(std::index_sequence< I... >)
std::vector< DataObjID > to_DataObjID(const std::vector< std::string > &in)
In operator()(In &&in) const
auto operator()(const Handle< Gaudi::Range_< I, IT >> &h) -> const In
DataObjectHandle.h GaudiKernel/DataObjectHandle.h.
static auto apply(const Algorithm &algo, Handles &handles)
Handles make_vector_of_handles(IDataHandleHolder *owner, const std::vector< DataObjID > &init)
std::remove_pointer_t< typename Container::value_type > c_remove_ptr_t
DataHandleMixin(std::string name, ISvcLocator *pSvcLocator, RepeatValues_< KeyValue, N_in > const &inputs, RepeatValues_< KeyValue, N_out > const &outputs)
std::enable_if_t<!std::is_pointer_v< X >, ref_t > at(size_type i) const
constexpr unsigned int inputLocationSize() const
bool check_sizes(const A &a, const B &b, const C &... c) noexcept
Compare sizes of 3 or more containers.
void operator()(F &&f, Arg &&arg) const
static auto apply(const Algorithm &algo, const EventContext &ctx, Handles &handles)
typename Tr::template InputHandle< T > InputHandle_t
std::conditional_t< is_tool_v< T >, ToolHandle_t< T >, DataObjectReadHandle< T > > DefaultInputHandle
DataHandleMixin(std::string name, ISvcLocator *pSvcLocator, const OArgs &outputs, std::index_sequence< J... >)
std::conditional_t< is_pointer, ptr_t, val_t > value_type
std::enable_if_t< std::is_pointer_v< X >, ptr_t > back() const
typename details::detector< Default, void, Op, Args... >::type detected_or_t
Base class from which all concrete algorithm classes should be derived.
auto applyPostProcessing(const Fun &fun, Container &c) -> decltype(fun.postprocess(c), void())
constexpr unsigned int inputLocationSize() const
void put(const OutHandle &out_handle, OptOut &&out)
static auto apply(const Algorithm &algo, Handles &handles)
decltype(std::declval< T >().has_value(), std::declval< T >().value()) is_optional_
typename Tr::template OutputHandle< T > OutputHandle_t
constexpr struct Gaudi::Functional::details::deref_t deref
std::tuple< details::OutputHandle_t< Traits_, Out >... > m_outputs
std::enable_if_t< std::is_pointer_v< X >, ptr_t > at(size_type i) const
std::enable_if_t< is_optional_v< Arg > > require_is_optional
void push_back(T &&container)
void updateHandleLocation(DataHandleMixin< Out, In, Tr > &parent, const std::string &prop, const std::string &newLoc)
Header file for std:chrono::duration-based Counters.
friend bool operator==(const iterator &lhs, const iterator &rhs)
std::tuple< details::OutputHandle_t< Traits_, Out >... > m_outputs
std::enable_if_t<!std::is_pointer_v< X >, ref_t > back() const
bool isReEntrant() const override
const In & operator()(const In &in) const
typename is_detected< Op, Args... >::type detected_t
T * put(std::unique_ptr< T > object) const
Register object in transient store.
decltype(auto) verifySizes(Args &... args)
Verify the data container sizes have the same sizes.
static auto apply(const Algorithm &algo, const EventContext &ctx, Handles &handles)
friend bool operator!=(const iterator &lhs, const iterator &rhs)
typename it_t::difference_type difference_type
constexpr bool is_optional_v
void push_back(Container &c, const Value &v, std::false_type)
T & deref_if(T *const t, std::true_type)
decltype(get_values_helper< Value >(std::make_index_sequence< N >())) RepeatValues_
constexpr unsigned int outputLocationSize() const
typename it_t::iterator_category value_type
typename it_t::pointer pointer
typename ContainerVector::const_iterator it_t
void updateHandleLocations(DataHandleMixin< Out, In, Tr > &parent, const std::string &prop, const std::vector< std::string > &newLocs)
auto operator()(Container &c, Value &&v) const -> decltype(c.insert(v))
std::add_lvalue_reference_t< val_t > ref_t
typename it_t::reference reference
auto operator()(const Handle< Gaudi::NamedRange_< I, IT >> &h) -> const In
Gaudi::cpp17::detected_or_t< Base, detail2::BaseClass_t, Tr > BaseClass_t
void printSizes(OS &out, Arg &&arg, Args &&... args)
Print the parameters.
typename T::value_type value_type_of_t
constexpr static const auto FAILURE
DataHandleMixin(std::string name, ISvcLocator *pSvcLocator, std::tuple<>={}, std::tuple<>={})
std::conditional_t< is_pointer, ptr_t, ref_t > ret_t
constexpr struct Gaudi::Functional::details::insert_t insert
auto operator()(const Handle< I > &h) -> const In
Gaudi::cpp17::detected_or_t< DataObjectWriteHandle< T >, detail2::OutputHandle_t, Tr, T > OutputHandle_t
typename filter_evtcontext_t< In... >::type filter_evtcontext
DataHandleMixin(std::string name, ISvcLocator *pSvcLocator, RepeatValues_< KeyValue, N_in > const &inputs)
vector_of_const_()=default
std::add_pointer_t< val_t > ptr_t
DataHandleMixin(std::string name, ISvcLocator *locator, const KeyValue &input, RepeatValues_< KeyValue, N_out > const &outputs)
decltype(auto) range(Args &&... args)
Zips multiple containers together to form a single range.
Stream & ostream_joiner(Stream &os, Iterator first, Iterator last, Separator sep, OutputElement output=OutputElement{})
DataHandleMixin(std::string name, ISvcLocator *locator, const KeyValue &input)
auto getKey(const Handle &h) -> decltype(h.objKey())
std::conditional_t< is_optional_v< T >, Gaudi::cpp17::detected_t< details2::value_type_of_t, T >, T > remove_optional_t
bool is_null(size_type i) const