diff --git a/src/core/ActionRegister.h b/src/core/ActionRegister.h index 9f56bbc928..cba3125bf4 100644 --- a/src/core/ActionRegister.h +++ b/src/core/ActionRegister.h @@ -88,11 +88,36 @@ ActionRegister& actionRegister(); std::ostream & operator<<(std::ostream &log,const ActionRegister&ar); -} +template +inline constexpr bool isActionType = std::is_base_of::value; +//in C++20 you we'll make this a concept +//template +//concept ActionType = std::is_base_of<::PLMD::Action, T>::value; +//so the template will be templateclass ActionRegistration{...} +//without the explicit need of the static assert + +///Each instance of this specialized class represents an action that can be called +///with the specified directive. +///As soon it goes out of scope it will deregister the directive from the singleton ActionRegister +template +class ActionRegistration { + static std::unique_ptr create(const ActionOptions&ao) { + return std::make_unique(ao); + } +public: + ///On construction register the ActionClass with the wanted directive + ActionRegistration(std::string_view directive) { + static_assert(isActionType, + "ActionRegistration accepts only class that inherit from Action"); + actionRegister().add(directive.data(),create,ActionClass::registerKeywords); + } + ///On destruction deregister the ActionClass (useful when you unload a shared object) + ~ActionRegistration() {actionRegister().remove(create);} +}; +} //PLMD #define PLUMED_CONCATENATE_DIRECT(s1, s2) s1##s2 #define PLUMED_CONCATENATE(s1, s2) PLUMED_CONCATENATE_DIRECT(s1, s2) -#define PLUMED_UNIQUENAME(str) PLUMED_CONCATENATE(str, __LINE__) /// Shortcut for Action registration /// \relates PLMD::ActionRegister @@ -101,13 +126,7 @@ std::ostream & operator<<(std::ostream &log,const ActionRegister&ar); /// \param directive a string containing the corresponding directive /// This macro should be used in the .cpp file of the corresponding class #define PLUMED_REGISTER_ACTION(classname,directive) \ - namespace { class PLUMED_UNIQUENAME(classname##RegisterMe){ \ - static std::unique_ptr create(const PLMD::ActionOptions&ao){return std::make_unique(ao);} \ - public: \ - PLUMED_UNIQUENAME(classname##RegisterMe)(){PLMD::actionRegister().add(directive,create,classname::registerKeywords);} \ - ~PLUMED_UNIQUENAME(classname##RegisterMe)(){PLMD::actionRegister().remove(create);} \ - } PLUMED_UNIQUENAME(classname##RegisterMe); } - - + namespace {::PLMD::ActionRegistration \ + PLUMED_CONCATENATE(classname##Registerer,__LINE__)(directive);} #endif