103 VariableSet() : m_vtable( VariableSetFunctions::getInstance() ) {}
107 m_vtable( VariableSetFunctions::getInstance() ) {
134 void mergeKeepVariables(
const VariableSet& from );
140 void mergeReplaceVariables(
const VariableSet& from );
159 template <
typename T>
160 auto insertVariable(
const std::string& name,
const T& value )
167 template <
typename T>
168 auto getVariable(
const std::string& name )
const ->
const T&;
169 template <
typename T>
177 template <
typename T>
178 auto getVariableHandle(
const std::string& name )
const ->
const VariableHandle<T>;
184 template <
typename H>
185 bool isHandleValid(
const H& handle )
const;
190 template <
typename T>
198 template <
typename T>
208 template <
typename H>
209 bool deleteVariable( H& handle );
214 template <
typename T>
215 auto existsVariable(
const std::string& name )
const -> Utils::optional<VariableHandle<T>>;
229 template <
typename T>
237 template <typename T>
238 bool deleteAllVariables();
245 template <typename T>
254 template <typename H>
255 auto getAllVariablesFromHandle( const H& handle )
261 template <typename T>
262 size_t numberOf() const;
272 template <typename... TYPES>
274 using types = Utils::TypeList<TYPES...>;
292 virtual void operator()( std::any&& in, std::any&& userParam )
const = 0;
321 void operator()( std::any&& in, std::any&& userParam )
const override;
335 template <
typename T,
typename F>
336 bool addOperator( F&& f );
341 template <
typename T>
350 template <
typename T,
typename F>
351 void addOrReplaceOperator( F&& f );
357 template <
typename T>
358 bool removeOperator();
368 template <
typename T,
typename F,
bool WithUserParam>
369 struct MakeVisitOperatorHelper {
370 auto makeOperator( F& f ) -> OperatorsStorageType::value_type;
375 template <
typename T,
typename F>
376 auto makeVisitorOperator( F& f ) -> OperatorsStorageType::value_type;
379 OperatorsStorageType m_visitorOperator;
392 template <
typename F>
393 void visit( F&& visitor )
const;
396 template <
typename F,
typename T>
397 void visit( F&& visitor, T& userParams )
const;
400 template <
typename F,
typename T>
401 void visit( F&& visitor, T&& userParams )
const;
427 template <
typename P =
bool>
428 void visitDynamic( DynamicVisitorBase& visitor, P&& params = P {} )
const;
447 template <
typename F>
448 void visitStatic( F&& visitor )
const;
451 template <
typename F,
typename T>
452 void visitStatic( F&& visitor, T& userParams )
const;
455 template <
typename F,
typename T>
456 void visitStatic( F&& visitor, T&& userParams )
const;
461 template <
typename T>
469 template <
typename T>
470 auto addVariableType() -> Utils::optional<VariableContainer<T>*>;
475 template <
typename F,
typename T>
476 using VisitFunction =
481 template <
typename F,
typename T,
typename U>
482 using VisitFunctionWithUserParam =
488 template <
typename F,
typename T>
489 static constexpr bool has_visit_callable_v =
490 Ra::Core::Utils::is_detected<VisitFunction, F, T>::value;
493 template <
typename F,
typename T,
typename U>
494 static constexpr bool has_visit_callable_with_user_param_v =
495 Ra::Core::Utils::is_detected<VisitFunctionWithUserParam, F, T, U>::value;
498 template <
typename F,
template <
typename...>
typename TYPESLIST,
typename... TYPES>
499 void visitImpl( F&& visitor, TYPESLIST<TYPES...> )
const;
501 template <
typename F,
typename T>
502 void visitImplHelper( F& visitor )
const;
505 template <
typename F,
typename U,
template <
typename...>
typename TYPESLIST,
typename... TYPES>
506 void visitImplUserParam( F&& visitor, U&& userParam, TYPESLIST<TYPES...> )
const;
508 template <
typename F,
typename U,
typename T>
509 void visitImplHelperUserParam( F& visitor, U&& userParams )
const;
518 class VariableSetFunctions
525 using VisitFunctorType =
528 const DynamicVisitorBase& )>;
530 VariableSetFunctions(
const VariableSetFunctions& ) =
delete;
531 void operator=(
const VariableSetFunctions& ) =
delete;
534 VariableSetFunctions() =
default;
535 ~VariableSetFunctions() =
default;
539 static auto getInstance() -> VariableSetFunctions*;
548 VariableSetFunctions* m_vtable;
563 template <
typename T>
564 auto createVariableStorage() -> VariableContainer<T>*;
568 template <
typename T>
569 auto getVariableStorage() const -> VariableContainer<T>&;
573 template <typename T>
574 void removeVariableStorage();
584auto VariableSet::createVariableStorage() -> VariableContainer<T>* {
586 return std::any_cast<VariableContainer<T>>( &( m_variables[
std::type_index {
typeid( T ) }] ) );
590auto VariableSet::getVariableStorage() const -> VariableContainer<T>& {
591 return std::any_cast<VariableContainer<T>&>( m_variables[
std::type_index {
typeid( T ) }] );
595void VariableSet::removeVariableStorage() {
597 m_variables.
erase( type );
598 m_typeIndexToVtableIndex.
erase( type );
601 m_storedType.
erase( newEnd, m_storedType.
end() );
608auto VariableSet::insertVariable(
const std::string& name,
const T& value )
610 auto typeAccess = existsVariableType<T>();
612 if ( !typeAccess ) { typeAccess = addVariableType<T>(); }
614 return ( *typeAccess )->insert( { name, value } );
618auto VariableSet::getVariable(
const std::string& name ) -> T& {
623auto VariableSet::getVariable(
const std::string& name )
const ->
const T& {
624 return getVariableHandle<T>( name )->second;
629 assert( existsVariableType<T>() );
630 return getVariableStorage<T>().find( name );
634bool VariableSet::isHandleValid(
const H& handle )
const {
636 return handle != getVariableStorage<VariableTypeFromHandle<H>>().end();
640auto VariableSet::setVariable(
const std::string& name,
const T& value )
642 auto typeAccess = existsVariableType<T>();
644 if ( !typeAccess ) { typeAccess = addVariableType<T>(); }
647 return ( *typeAccess )->insert_or_assign( name, value );
652 if (
auto typeAccess = existsVariableType<T>(); typeAccess ) {
653 auto removed = ( *typeAccess )->erase( name );
655 if ( numberOf<T>() == 0 ) { deleteAllVariables<T>(); }
662bool VariableSet::deleteVariable( H& handle ) {
663 assert( isHandleValid( handle ) );
664 auto varname = handle->first;
665 handle = getVariableStorage<VariableTypeFromHandle<H>>().end();
666 return deleteVariable<VariableTypeFromHandle<H>>( varname );
671 -> Utils::optional<VariableHandle<T>> {
673 if (
auto typeAccess = existsVariableType<T>(); typeAccess ) {
674 auto itr = ( *typeAccess )->find( name );
675 if ( itr != ( *typeAccess )->cend() ) {
return itr; }
688auto VariableSet::addVariableType() -> Utils::optional<VariableContainer<T>*> {
689 auto storage = createVariableStorage<T>();
692 auto it =
std::find( m_vtable->m_storedType.begin(), m_vtable->m_storedType.end(), tidx );
695 m_typeIndexToVtableIndex[tidx] = it - m_vtable->m_storedType.begin();
699 if ( it == m_vtable->m_storedType.end() ) {
701 m_vtable->m_storedType.emplace_back( tidx );
703 m_vtable->m_mergeKeepFunctions.emplace_back(
706 if ( !toStorageAccess ) { toStorageAccess = to.addVariableType<T>(); }
707 auto& toStorage = *( toStorageAccess.value() );
708 auto& fromStorage = from.getVariableStorage<T>();
709 for (
const auto& t : fromStorage ) {
710 toStorage.insert( t );
714 m_vtable->m_mergeReplaceFunctions.emplace_back(
715 [](
const VariableSet& from, VariableSet& to ) {
716 auto toStorageAccess = to.existsVariableType<T>();
717 if ( !toStorageAccess ) { toStorageAccess = to.addVariableType<T>(); }
718 auto& toStorage = *( toStorageAccess.value() );
719 auto& fromStorage = from.getVariableStorage<T>();
720 for (
const auto& t : fromStorage ) {
721 toStorage.insert_or_assign( t.first, t.second );
725 m_vtable->m_sizeFunctions.emplace_back(
726 [](
const VariableSet& c ) {
return c.getVariableStorage<T>().size(); } );
728 m_vtable->m_visitFunctions.emplace_back(
729 [](
const VariableSet& c,
const DynamicVisitorBase& v )
731 auto id = getVariableVisitTypeIndex<T>();
732 if ( v.accept(
id ) ) {
733 auto& visitedStorage = c.getVariableStorage<T>();
734 auto coll =
std::ref( visitedStorage );
735 return {
true, [coll]( DynamicVisitorBase& visitor, std::any&& userParam ) {
736 for (
auto&& t : coll.get() ) {
742 else {
return {
false,
nullptr }; }
751 if ( iter == m_variables.
cend() ) {
return {}; }
752 else {
return std::any_cast<VariableSet::VariableContainer<T>>( &( iter->second ) ); }
756bool VariableSet::deleteAllVariables() {
757 if ( existsVariableType<T>() ) {
758 removeVariableStorage<T>();
768 assert( existsVariableType<T>() );
770 return getVariableStorage<T>();
774auto VariableSet::getAllVariablesFromHandle(
const H& )
777 return getVariableStorage<VariableTypeFromHandle<H>>();
781size_t VariableSet::numberOf()
const {
782 if (
auto variables = existsVariableType<T>(); variables ) {
return ( *variables )->size(); }
789void VariableSet::visitDynamic( DynamicVisitorBase& visitor, P&& params )
const {
790 for (
const auto& [type, index] : m_typeIndexToVtableIndex ) {
791 auto [accepted, loop] = m_vtable->m_visitFunctions[index]( *
this, visitor );
797void VariableSet::visitStatic( F&& visitor )
const {
798 visitImpl( visitor,
typename std::decay_t<F>::types {} );
801template <
typename F,
template <
typename...>
typename TYPESLIST,
typename... TYPES>
802void VariableSet::visitImpl( F&& visitor, TYPESLIST<TYPES...> )
const {
803 ( ..., visitImplHelper<std::decay_t<F>, TYPES>( visitor ) );
806template <
typename F,
typename T>
807void VariableSet::visitImplHelper( F& visitor )
const {
808 static_assert( has_visit_callable_v<F, T>,
809 "Static visitors must provide a function with profile "
810 "void( const std::string& name, [const ]T[&] value) for each "
811 "declared visitable type T" );
812 if (
auto variables = existsVariableType<T>() ) {
813 for (
auto& element : *( variables.value() ) ) {
814 visitor( element.first, element.second );
819template <
typename F,
typename U>
820void VariableSet::visitStatic( F&& visitor, U& userParams )
const {
822 visitor,
std::forward<U>( userParams ),
typename std::decay_t<F>::types {} );
825template <
typename F,
typename U>
826void VariableSet::visitStatic( F&& visitor, U&& userParams )
const {
828 visitor,
std::forward<U>( userParams ),
typename std::decay_t<F>::types {} );
831template <
typename F,
typename U,
template <
typename...>
typename TYPESLIST,
typename... TYPES>
832void VariableSet::visitImplUserParam( F&& visitor, U&& userParam, TYPESLIST<TYPES...> )
const {
834 visitImplHelperUserParam<std::decay_t<F>, U, TYPES>( visitor,
838template <
typename F,
typename U,
typename T>
839void VariableSet::visitImplHelperUserParam( F& visitor, U&& userParams )
const {
840 static_assert( has_visit_callable_with_user_param_v<F, T, U>,
841 "Static visitors must provide a function with profile "
842 "void( const std::string& name, [const ]T[&] value, [const] U&&) for each "
843 "declared visitable type T" );
844 if (
auto variables = existsVariableType<T>(); variables ) {
845 for (
auto& element : *( variables.value() ) ) {
846 visitor( element.first, element.second,
std::forward<U>( userParams ) );
851template <
typename T,
typename F>
852bool VariableSet::DynamicVisitor::addOperator( F&& f ) {
853 auto [it, inserted] = m_visitorOperator.
insert( makeVisitorOperator<T, F>( f ) );
858bool VariableSet::DynamicVisitor::hasOperator() {
859 return m_visitorOperator.find( getVariableVisitTypeIndex<T>() ) != m_visitorOperator.end();
862template <
typename T,
typename F>
863void VariableSet::DynamicVisitor::addOrReplaceOperator( F&& f ) {
864 auto op = makeVisitorOperator<T, F>( f );
865 m_visitorOperator.insert_or_assign( op.first, op.second );
869bool VariableSet::DynamicVisitor::removeOperator() {
870 assert( hasOperator<T>() );
871 auto res = m_visitorOperator.erase( getVariableVisitTypeIndex<T>() ) > 0;
875template <
typename T,
typename F>
876struct VariableSet::DynamicVisitor::MakeVisitOperatorHelper<T, F, true> {
877 inline auto makeOperator( F& f ) -> OperatorsStorageType::value_type {
878 return { getVariableVisitTypeIndex<T>(), [&f]( std::any& a, std::any&& userParam ) {
879 auto rp = std::any_cast<std::reference_wrapper<VariableSet::Variable<T>>&>( a );
886template <
typename T,
typename F>
887struct VariableSet::DynamicVisitor::MakeVisitOperatorHelper<T, F, false> {
888 inline auto makeOperator( F& f ) -> OperatorsStorageType::value_type {
889 return { getVariableVisitTypeIndex<T>(), [&f]( std::any& a, std::any&& ) {
890 auto rp = std::any_cast<std::reference_wrapper<VariableSet::Variable<T>>&>( a );
892 f( p.first, p.second );
897template <
class T,
class F>
898inline auto VariableSet::DynamicVisitor::makeVisitorOperator( F& f )
899 -> OperatorsStorageType::value_type {
900 auto opBuilder = MakeVisitOperatorHelper < T, F,
901 std::is_invocable<F, const std::string&, T, std::any&&>::value ||
902 std::is_invocable<F, const std::string&, T&, std::any&&>::value > {};
903 return opBuilder.makeOperator( f );
907inline void VariableSet::visit( F&& visitor )
const {
909 visitDynamic( visitor );
911 else { visitStatic( visitor ); }
914template <
typename F,
typename T>
915inline void VariableSet::visit( F&& visitor, T& userParams )
const {
922template <
typename F,
typename T>
923inline void VariableSet::visit( F&& visitor, T&& userParams )
const {