23#include <initializer_list>
27#include <source_location>
40 template <
template <
typename>
class Handle,
typename I>
43 inline std::vector<DataObjID>
to_DataObjID(
const std::vector<std::string>& in ) {
44 std::vector<DataObjID> out;
45 out.reserve( in.size() );
46 std::transform( in.begin(), in.end(), std::back_inserter( out ),
47 [](
const std::string& i ) { return DataObjID{ i }; } );
56 typename T::value_type;
66 template <is_optional T>
68 using type = T::value_type;
77 template <
typename F,
typename Arg>
80 return std::invoke( std::forward<F>( f ), std::forward<Arg>( arg ) );
82 template <
typename F, is_optional Arg>
84 if ( arg ) std::invoke( std::forward<F>( f ), *std::forward<Arg>( arg ) );
86 } invoke_optionally{};
89 template <
typename Value, auto>
90 using repeat_t = Value;
91 template <
typename Value, auto N>
93 decltype( []<std::size_t... I>( std::index_sequence<I...> ) -> std::tuple<repeat_t<Value, I>...> {
94 }( std::make_index_sequence<N>{} ) );
96 template <
typename Value, std::size_t... I>
98 return std::make_tuple( ( (
void)I, Value{} )... );
101 template <
typename Value, auto N>
106 template <std::derived_from<DataObject> Out1, std::convertible_to<Out1> Out2>
108 return out_handle.
put( std::make_unique<Out1>( std::forward<Out2>( out ) ) );
111 template <
typename Out1, std::convertible_to<Out1> Out2>
113 return out_handle.put( std::forward<Out2>( out ) );
116 template <
template <
typename>
class Handle,
typename Out,
typename Value>
118 return out_handle.
put( std::forward<Value>( out ) );
122 template <
typename OutHandle,
typename OptOut>
123 requires( is_optional<OptOut> )
124 void put(
const OutHandle& out_handle, OptOut&& out ) {
125 if ( out )
put( out_handle, *std::forward<OptOut>( out ) );
135 template <
typename Container>
138 template <
typename Container,
typename Value>
139 auto operator()( Container& c, Value&& v )
const ->
decltype( c.push_back( v ) ) {
140 return c.push_back( std::forward<Value>( v ) );
143 template <
typename Container,
typename Value>
144 auto operator()( Container& c, Value&& v )
const ->
decltype( c.insert( v ) ) {
145 return c.insert( std::forward<Value>( v ) );
149 template <
typename Container,
typename Value>
150 requires( std::is_pointer_v<typename Container::value_type> &&
151 std::is_convertible_v<Value, c_remove_ptr_t<Container>> )
152 auto operator()( Container& c, Value&& v )
const {
161 template <
typename In>
162 requires( !std::is_pointer_v<In> )
163 const In&
operator()(
const In& in )
const {
167 template <
typename In>
168 requires( !std::is_pointer_v<std::decay_t<In>> )
169 In
operator()( In&& in )
const {
170 return std::forward<In>( in );
173 template <
typename In>
175 assert( in !=
nullptr );
183 template <
typename T>
184 constexpr static bool is_gaudi_range_v =
false;
186 template <
typename T>
187 constexpr static bool is_gaudi_range_v<Gaudi::Range_<T>> =
true;
189 template <
typename T>
190 constexpr static bool is_gaudi_range_v<Gaudi::NamedRange_<T>> =
true;
192 template <
typename T>
193 constexpr static bool is_gaudi_range_v<std::optional<Gaudi::NamedRange_<T>>> =
true;
195 template <
typename In>
197 template <
template <
typename>
class Handle, std::convertible_to<In> I>
201 template <
template <
typename>
class Handle,
typename I>
205 template <
template <
typename>
class Handle,
typename I>
209 template <
template <
typename>
class Handle,
typename I>
213 template <
template <
typename>
class Handle,
typename I>
214 requires( std::is_convertible_v<I*, In> )
215 auto operator()(
const Handle<I>& h ) -> In {
216 return h.getIfExists();
220 template <
typename Iterator>
222 using traits = std::iterator_traits<Iterator>;
226 using iterator_category [[maybe_unused]] =
typename traits::iterator_category;
227 using difference_type [[maybe_unused]] =
typename traits::difference_type;
229 using value_type [[maybe_unused]] = std::remove_reference_t<reference>;
230 using pointer [[maybe_unused]] = std::add_pointer_t<value_type>;
257 requires std::bidirectional_iterator<Iterator>
266 requires std::random_access_iterator<Iterator>
272 requires std::random_access_iterator<Iterator>
278 requires std::random_access_iterator<Iterator>
284 requires std::random_access_iterator<Iterator>
290 requires std::random_access_iterator<Iterator>
292 return m_iter - other.m_iter;
295 requires std::random_access_iterator<Iterator>
303 template <
typename Container>
305 static constexpr bool is_pointer = std::is_pointer_v<Container>;
306 static constexpr bool is_range = details2::is_gaudi_range_v<Container>;
307 template <
typename C>
311 using ptr_t = std::add_pointer_t<val_t>;
315 constexpr static decltype( auto )
wrap( ContainerVector::const_reference t ) {
322 constexpr static auto wrap( ContainerVector::const_iterator i ) {
331 using value_type = std::conditional_t<is_pointer, ptr_t, val_t>;
336 template <
typename T>
337 requires( is_pointer || is_range )
341 template <
typename C = Container>
342 requires( !std::is_pointer_v<C> && !details2::is_gaudi_range_v<C> )
347 template <
typename C = Container>
348 requires( !std::is_pointer_v<C> && !details2::is_gaudi_range_v<C> )
360 template <
template <
typename>
class Handle,
typename I>
366 template <
typename Algorithm>
369 [ptr = &
handles, parent]( auto& self_ ) {
372 ptr->reserve( self.value().size() );
373 std::ranges::transform( self.value(), std::back_inserter( *ptr ),
374 [&](
const auto& location ) -> Handle<I> {
375 return { location, parent };
388 template <
typename Algorithm>
390 :
m_payload{
std::make_unique<Payload>( parent, keys ) } {}
393 template <
typename A,
typename K>
395 template <
typename A,
typename Name,
typename Keys>
406 template <
typename Out>
407 void put( Out&& out )
const {
408 auto const n =
size();
409 if ( out.size() != n ) {
411 std::string{ std::source_location::current().function_name() } +
": expected " +
412 std::to_string( n ) +
" containers, got " + std::to_string( out.size() ) +
" instead",
424 template <
typename T>
426 template <
typename T>
429 template <
typename Arg>
434 template <
typename T>
439 template <
typename Arg>
441 template <
typename Arg>
443 template <
typename... Args>
446 template <
typename... T>
449 template <
typename H>
455 template <
typename Vectors>
456 decltype( auto )
getLocations( Vectors
const& vectors,
unsigned int i ) {
458 [i](
auto const&... elems ) ->
decltype(
auto ) {
return *std::array{ &elems.locations()... }.at( i ); },
462 template <
typename F>
465 return std::forward<F>( f )();
474 template <
typename Algo>
481 template <
typename Tr>
484 template <
typename Tr,
typename Default>
488 template <
typename Tr,
typename Default>
489 requires requires {
typename Tr::BaseClass; }
494 template <
typename T,
typename Tr,
template <
typename...>
typename Default>
498 template <
typename T,
typename Tr,
template <
typename...>
typename Default>
503 template <
typename Tr,
template <
typename...>
typename Default>
505 template <
typename T>
508 template <
typename T,
typename Tr,
template <
typename...>
typename Default>
513 template <
typename T,
typename Tr,
template <
typename...>
typename Default>
517 template <
typename T,
typename Tr,
template <
typename...>
typename Default>
522 template <
typename Tr,
template <
typename...>
typename Default>
524 template <
typename T>
527 template <
typename T,
typename Tr,
template <
typename...>
typename Default>
532 template <
typename T>
535 template <
typename T>
539 template <algtool_
interface T>
547 template <
typename T>
554 template <
typename Tr,
typename Default = Gaudi::Algorithm>
560 template <
typename Tr,
typename T>
563 template <
typename Tr,
typename T>
566 template <
typename T>
570 using KeyValue = std::pair<std::string, std::string>;
571 using KeyValues = std::pair<std::string, std::vector<std::string>>;
577 :
value{
std::move( name_ ), { std::move( location_ ) } } {}
582 LocationSpec( std::string name_, std::initializer_list<std::string> locations_ )
587 throw GaudiException(
"Expected a scalar location specification",
"Gaudi::Functional::details::LocationSpec",
595 template <
typename Arg>
603 template <
typename T>
607 template <
typename T>
611 template <
typename Arg>
614 template <
typename... Args>
617 template <
typename... Args>
621 template <
typename First,
typename... Rest>
625 template <
typename... Args>
628 template <
typename Tuple>
632 template <
typename First,
typename... Rest>
636 template <
typename Tuple>
639 template <
typename Tuple,
typename T>
641 template <
typename T,
typename... Elements>
644 template <
typename Tuple,
typename T>
646 template <
typename T,
typename... Elements>
648 ( std::constructible_from<Elements, T> && ... );
650 template <
typename... Args>
652 template <
typename First,
typename... Rest>
655 template <
bool starts_with_event_context,
typename InputSpecTuple>
657 std::conditional_t<starts_with_event_context, InputSpecTuple, std::tuple<>>{};
659 template <
typename Tuple,
typename Spec, std::size_t... I>
660 Tuple
location_specs_tuple( std::initializer_list<Spec> specs, std::index_sequence<I...>,
const char* component ) {
661 if constexpr (
sizeof...( I ) == 1 ) {
662 if ( specs.size() == 0 )
return Tuple{ Spec{} };
664 if ( specs.size() !=
sizeof...( I ) ) {
667 return Tuple{ *std::next( specs.begin(), I )... };
670 template <
typename Tuple>
675 static constexpr auto indices = std::make_index_sequence<std::tuple_size_v<Tuple>>{};
678 requires( std::tuple_size_v<Tuple> == 0 )
681 template <
typename... Specs>
683 requires(
sizeof...( Specs ) > 0 && std::constructible_from<Tuple, Specs...> )
684 :
m_specs{
std::forward<Specs>( specs )... } {}
685 template <
typename... Args>
687 requires(
sizeof...( Args ) > 1 && std::tuple_size_v<Tuple> == 1 && std::constructible_from<
First, Args...> )
690 requires( std::tuple_size_v<Tuple> == 1 && std::constructible_from<First, std::string, std::string> )
693 requires( std::tuple_size_v<Tuple> == 1 && std::constructible_from<First, std::string, std::vector<std::string>> )
710 template <
typename Traits>
712 std::is_base_of_v<Gaudi::details::LegacyAlgorithmAdapter, details::BaseClass_t<Traits>>;
716 template <
typename Handle,
typename Algo>
717 auto get(
const Handle& handle,
const Algo&,
723 template <
typename Algo>
728 template <
template <
typename>
class Handle,
typename In,
typename Algo>
730 return handle.
get( ctx );
733 template <
typename IFace,
typename Algo>
735 return handle.bind( ctx );
738 template <
typename Handle>
739 auto getKey(
const Handle& h ) ->
decltype( h.objKey() ) {
743 template <
template <
typename>
class Handle,
typename T>
745 return h.locations();
748 template <
typename OutputSpec,
typename InputSpec,
typename Traits_>
751 template <
typename Outputs,
typename Traits_,
typename... Args>
754 template <
typename... Out,
typename... In,
typename Traits_>
755 requires( std::derived_from<BaseClass_t<Traits_>,
Algorithm> && !std::disjunction_v<std::is_void<Out>...> )
759 constexpr static std::size_t
N_in =
sizeof...( In );
760 constexpr static std::size_t
N_out =
sizeof...( Out );
763 template <
typename IArgs,
typename OArgs, std::size_t... I, std::size_t... J>
765 const OArgs& outputs, std::index_sequence<J...> )
773 using InputHandles = std::tuple<details::InputHandle_t<Traits_, In>...>;
784 template <std::
size_t N>
786 template <std::
size_t N>
788 template <std::size_t... I>
795 template <std::size_t... I>
806 requires( N_in == 0 && N_out == 0 )
807 : DataHandleMixin(
std::move( name ), locator,
std::tuple<>{}, InputSpecs::indices, std::tuple<>{},
808 OutputSpecs::indices ) {}
814 InputSpecs::indices,
std::tuple<>{}, OutputSpecs::indices ) {}
820 OutputSpecs::indices ) {}
826 OutputSpecs::indices ) {}
832 InputSpecs::indices, outputs.tuple(), outputs.indices ) {}
836 requires(
N_out != 0 )
837 :
DataHandleMixin(
std::move( name ), locator, inputs.tuple(), inputs.indices, outputs.tuple(),
846 template <std::
size_t N = 0>
852 template <
typename T>
858 template <std::
size_t N = 0>
862 return std::get<input_handle_index<N>>(
m_inputs ).at( n ).key();
872 auto size = [](
const auto& handle ) {
874 return static_cast<unsigned int>( handle.size() );
880 size](
const auto&... handles ) {
return std::array{ size( handles )... }.at( i ); },
898 template <std::
size_t N = 0>
900 requires(
N_out > 0 )
904 template <
typename T>
906 requires(
N_out > 0 )
910 template <std::
size_t N = 0>
914 return std::get<N>(
m_outputs ).at( n ).key();
924 template <
typename Algorithm>
927 [&](
const auto&... handle ) ->
decltype(
auto ) {
return algo(
get( handle, algo, ctx )... ); },
m_inputs );
938 template <
typename InputSpec,
typename Traits_>
944 template <
typename OutHandles,
typename Outputs>
945 void put_results(
const OutHandles& out_handles, Outputs&& outputs ) {
946 [&]<std::size_t... I>( std::index_sequence<I...> ) {
947 (
put( std::get<I>( out_handles ), std::get<I>( std::forward<Outputs>( outputs ) ) ), ... );
948 }( std::make_index_sequence<std::tuple_size_v<std::remove_reference_t<Outputs>>>{} );
951 template <
typename Algorithm,
typename OutHandles = std::tuple<>>
953 requires( std::tuple_size_v<OutHandles> <= 1 )
955 return execute( algo, [&] {
956 if constexpr ( std::tuple_size_v<OutHandles> == 0 ) {
957 algo.invoke( algo, ctx );
959 put( std::get<0>( out_handles ), algo.invoke( algo, ctx ) );
961 return FilterDecision::PASSED;
965 template <
typename Algorithm,
typename OutHandles>
968 put_results( out_handles, algo.invoke( algo, ctx ) );
973 template <
typename Algorithm,
typename OutHandles>
977 [&](
bool passed,
auto&&... data ) {
978 put_results( out_handles, std::forward_as_tuple( std::forward<
decltype( data )>( data )... ) );
981 algo.invoke( algo, ctx ) )
bool PyHelper setProperty(IInterface *p, char *name, char *value)
boost::spirit::classic::position_iterator2< ForwardIterator > Iterator
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
DataObjectHandle.h GaudiKernel/DataObjectHandle.h.
T * put(std::unique_ptr< T > object) const
Register object in transient store.
This class represents an entry point to all the event specific data.
Base class from which all concrete algorithm classes should be derived.
static constexpr bool all_input_locations_are_vectors
unsigned int outputLocationSize() const
std::tuple< details::OutputHandle_t< Traits_, Out >... > OutputHandles
static constexpr bool starts_with_event_context
static constexpr std::size_t N_in
LocationSpec::KeyValue KeyValue
DataHandleMixin(std::string name, ISvcLocator *pSvcLocator, const IArgs &inputs, std::index_sequence< I... >, const OArgs &outputs, std::index_sequence< J... >)
DataHandleMixin(std::string name, ISvcLocator *locator, LegacyInputSpecs const &inputs)
decltype(auto) inputLocation(unsigned int i, unsigned int j) const
decltype(auto) outputLocation() const
DataHandleMixin(std::string name, ISvcLocator *locator, LegacyInputSpecs const &inputs, OutputSpecs const &outputs)
DataHandleMixin(std::string name, ISvcLocator *locator, InputSpecs const &inputs)
TailLocationSpecs_t< In... > LegacyInputSpecTuple
bool isReEntrant() const override
decltype(auto) inputLocation() const
LocationSpecs_t< Out... > OutputSpecTuple
static constexpr std::size_t input_handle_index
DataHandleMixin(std::string name, ISvcLocator *locator, InputSpecs const &inputs, OutputSpecs const &outputs)
static constexpr std::size_t N_input_locations
DataHandleMixin(std::string name, ISvcLocator *locator, OutputSpecs const &outputs)
auto input_location_handles(std::index_sequence< I... >) const
static constexpr std::size_t input_location_offset
static constexpr std::size_t N_out
unsigned int inputLocationSize(unsigned int i) const
static constexpr bool input_locations_are_vectors(std::index_sequence< I... >)
details::LocationSpecs< LegacyInputSpecTuple > LegacyInputSpecs
decltype(auto) inputLocation() const
details::LocationSpecs< InputSpecTuple > InputSpecs
decltype(auto) invoke(const Algorithm &algo, const EventContext &ctx) const
details::LocationSpecs< OutputSpecTuple > OutputSpecs
std::tuple_element_t< input_handle_index< N >, InputHandles > InputLocationHandle
decltype(auto) outputLocation(unsigned int n) const
decltype(auto) inputLocation(unsigned int n) const
unsigned int inputLocationSize() const
std::tuple< details::InputHandle_t< Traits_, In >... > InputHandles
DataHandleMixin(std::string name, ISvcLocator *locator)
LocationSpecs_t< In... > InputSpecTuple
DataHandleMixin(std::string name, ISvcLocator *locator, std::tuple<>={}, std::tuple<>={})
LocationSpec::KeyValues KeyValues
HandleVector(std::tuple< A, K > &&tup)
std::unique_ptr< Payload > m_payload
DataObjID const & at(size_t i) const
HandleVector(Algorithm *parent, std::pair< std::string, std::vector< std::string > > const &keys)
void put(Out &&out) const
std::vector< DataObjID > const & locations() const
HandleVector(std::tuple< A, Name, Keys > &&tup)
vector_of_const_< T > get(EventContext const &) const
std::vector< OutputHandleFor< Tr, Default >::template type< T > > const & handles() const
LocationSpecs(Args &&... args)
LocationSpecs(std::string name, std::string loc)
first_or_empty_t< Tuple > First
LocationSpecs(Tuple specs)
LocationSpecs(std::string name, std::vector< std::string > locs)
LocationSpecs(std::initializer_list< LocationSpec > specs)
auto with_context() const
Tuple const & tuple() const
static constexpr auto indices
LocationSpecs(Specs &&... specs)
LocationSpecs(std::initializer_list< First > specs)
constexpr indirect_iterator & operator+=(difference_type n)
constexpr indirect_iterator operator--(int)
constexpr indirect_iterator & operator++()
constexpr indirect_iterator & operator-=(difference_type n)
constexpr reference operator*() const
constexpr indirect_iterator(Iterator i)
constexpr indirect_iterator operator+(difference_type n) const
constexpr bool operator==(const indirect_iterator &rhs) const
std::iterator_traits< Iterator > traits
constexpr indirect_iterator operator-(difference_type n) const
constexpr difference_type operator-(const indirect_iterator &other) const
constexpr reference operator[](difference_type n) const
indirect_iterator()=default
constexpr indirect_iterator operator++(int)
constexpr indirect_iterator & operator--()
decltype(**m_iter) reference
static constexpr decltype(auto) wrap(ContainerVector::const_reference t)
static constexpr bool is_range
static constexpr auto wrap(ContainerVector::const_iterator i)
static constexpr bool is_pointer
std::add_pointer_t< val_t > ptr_t
ContainerVector m_containers
decltype(auto) back() const
void push_back(borrowed_value_t< C > &&)=delete
std::add_const_t< std::remove_pointer_t< C > > borrowed_value_t
vector_of_const_()=default
void push_back(T &&container)
void reserve(size_type size)
typename ContainerVector::size_type size_type
std::vector< std::conditional_t< is_range, std::remove_const_t< val_t >, ptr_t > > ContainerVector
std::conditional_t< is_pointer, ptr_t, val_t > value_type
borrowed_value_t< Container > val_t
decltype(auto) at(size_type i) const
void push_back(borrowed_value_t< C > &container)
decltype(auto) front() const
Implementation of property with value of concrete type.
Useful class for representation of "sequence" of the objects through the range of valid iterators.
Define general base for Gaudi exception.
virtual const std::string & message() const
error message to be printed
virtual const StatusCode & code() const
StatusCode for Exception.
virtual const std::string & tag() const
name tag for the exception, or exception type
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
This class is used for returning status codes from appropriate routines.
constexpr static const auto FAILURE
Gaudi::tagged_bool< class ImmediatelyInvokeHandler_tag > ImmediatelyInvokeHandler
typename Tr::BaseClass BaseClass_t
typename DefaultInputHandle< T >::type DefaultInputHandle_t
StatusCode execute_outputs(const Algorithm &algo, const EventContext &ctx, const OutHandles &out_handles)
typename detail2::InputHandle< T, Tr, detail2::DefaultInputHandle_t >::type InputHandle_t
auto get(const Handle &handle, const Algo &, const EventContext &) -> decltype(details::deref(handle.get()))
decltype(auto) getLocations(Vectors const &vectors, unsigned int i)
typename first_or_empty< Tuple >::type first_or_empty_t
auto getKey(const Handle &h) -> decltype(h.objKey())
constexpr auto empty_input_specs
typename TailLocationSpecs< Args... >::type TailLocationSpecs_t
std::vector< DataObjID > to_DataObjID(const std::vector< std::string > &in)
typename handle_vector_input< Arg >::type handle_vector_input_t
auto put(const DataObjectHandle< Out1 > &out_handle, Out2 &&out)
constexpr bool tuple_elements_are_v
std::tuple< LocationSpec_t< Args >... > LocationSpecs_t
typename detail2::OutputHandle< T, Tr, DataObjectWriteHandle >::type OutputHandle_t
StatusCode execute_single_output(const Algorithm &algo, const EventContext &ctx, const OutHandles &out_handles={})
constexpr bool first_is_event_context_v
constexpr struct Gaudi::Functional::details::deref_t deref
constexpr bool is_handle_vector_input_v
typename LocationSpecFor< std::remove_cvref_t< Arg > >::type LocationSpec_t
typename details2::value_type_of< T >::type remove_optional_t
constexpr bool is_event_context_v
detail2::BaseClass< Tr, Default >::type BaseClass_t
decltype(get_values_helper< Value >(std::make_index_sequence< N >())) RepeatValues_
StatusCode execute_filtered_outputs(const Algorithm &algo, const EventContext &ctx, const OutHandles &out_handles)
auto get_values_helper(std::index_sequence< I... >)
DataHandleMixin< Outputs, type_list< handle_vector_input_t< Args >... >, Traits_ > DataHandleVectorMixin
StatusCode execute(CommonMessagingBase const &alg, F &&f)
void put_results(const OutHandles &out_handles, Outputs &&outputs)
Tuple location_specs_tuple(std::initializer_list< Spec > specs, std::index_sequence< I... >, const char *component)
constexpr bool tuple_elements_constructible_from_v
EventContextHandle(std::tuple< Algo >)
Payload & operator=(Payload const &)=delete
std::vector< Handle< I > > handles
Gaudi::Property< std::vector< DataObjID > > property
Payload(Algorithm *parent, std::pair< std::string, std::vector< std::string > > const &keys)
Payload(Payload &&)=delete
Payload(Payload const &)=delete
Payload & operator=(Payload &&)=delete
LocationSpec::KeyValues type
LocationSpec::KeyValue type
LocationSpec::KeyValues type
LocationSpec(std::string name_, std::vector< std::string > locations_)
std::pair< std::string, std::string > KeyValue
std::pair< std::string, std::vector< std::string > > KeyValues
LocationSpec(std::string name_, std::initializer_list< std::string > locations_)
LocationSpec(std::string name_, const char *location_)
LocationSpec(std::string name_, std::string location_)
LocationSpecs_t< Rest... > type
const In & operator()(const In *in) const
typename OutputHandle< remove_optional_t< T >, Tr, Default >::type type
Tr::template OutputHandle< T > type
HandleVector< OutputHandleFor< Tr, Default >::template type, T > type
auto operator()(const Handle< std::optional< Gaudi::NamedRange_< I > > > &h) -> In
auto operator()(const Handle< I > &h) -> const In &
auto operator()(const Handle< Gaudi::NamedRange_< I > > &h) -> In
auto operator()(const Handle< Gaudi::Range_< I > > &h) -> In
std::remove_pointer_t< typename Container::value_type > c_remove_ptr_t
auto operator()(Container &c, Value &&v) const -> decltype(c.push_back(v))
auto operator()(Container &c, Value &&v) const -> decltype(c.insert(v))
decltype(auto) operator()(F &&f, Arg &&arg) const
void operator()(F &&f, Arg &&arg) const