diff --git a/include/class_loader/class_loader.hpp b/include/class_loader/class_loader.hpp index 5a5e077..5b52148 100644 --- a/include/class_loader/class_loader.hpp +++ b/include/class_loader/class_loader.hpp @@ -124,8 +124,8 @@ class ClassLoader * by InterfaceTraits of the Base class) * @return A std::shared_ptr to newly created plugin object */ - template, bool> = true> + template + requires InterfaceConstructible [[nodiscard]] std::shared_ptr createInstance( const std::string & derived_class_name, Args &&... args) { @@ -150,8 +150,8 @@ class ClassLoader * by InterfaceTraits of the Base class) * @return A std::unique_ptr to newly created plugin object. */ - template, bool> = true> + template + requires InterfaceConstructible [[nodiscard]] UniquePtr createUniqueInstance( const std::string & derived_class_name, Args &&... args) { @@ -177,8 +177,8 @@ class ClassLoader * by InterfaceTraits of the Base class) * @return An unmanaged (i.e. not a shared_ptr) Base* to newly created plugin object. */ - template, bool> = true> + template + requires InterfaceConstructible [[nodiscard]] Base * createUnmanagedInstance( const std::string & derived_class_name, Args &&... args) { @@ -196,8 +196,7 @@ class ClassLoader [[nodiscard]] bool isClassAvailable(const std::string & class_name) const { std::vector available_classes = getAvailableClasses(); - return std::find( - available_classes.begin(), available_classes.end(), class_name) != available_classes.end(); + return std::ranges::find(available_classes, class_name) != available_classes.end(); } /** @@ -314,8 +313,8 @@ class ClassLoader * by InterfaceTraits of the Base class) * @return A Base* to newly created plugin object. */ - template, bool> = true> + template + requires InterfaceConstructible Base * createRawInstance(const std::string & derived_class_name, bool managed, Args &&... args) { if (!managed) { diff --git a/include/class_loader/class_loader_core.hpp b/include/class_loader/class_loader_core.hpp index 917d9f4..418418b 100644 --- a/include/class_loader/class_loader_core.hpp +++ b/include/class_loader/class_loader_core.hpp @@ -32,6 +32,7 @@ #ifndef CLASS_LOADER__CLASS_LOADER_CORE_HPP_ #define CLASS_LOADER__CLASS_LOADER_CORE_HPP_ +#include #include #include #include @@ -277,25 +278,16 @@ registerPlugin(const std::string & class_name, const std::string & base_class_na [](AbstractMetaObjectBase * p) { getPluginBaseToFactoryMapMapMutex().lock(); MetaObjectGraveyardVector & graveyard = getMetaObjectGraveyard(); - for (auto iter = graveyard.begin(); iter != graveyard.end(); ++iter) { - if (*iter == p) { - graveyard.erase(iter); - break; - } + if (auto iter = std::ranges::find(graveyard, p); iter != graveyard.end()) { + graveyard.erase(iter); } BaseToFactoryMapMap & factory_map_map = getGlobalPluginBaseToFactoryMapMap(); - bool erase_flag = false; - for (auto & factory_map_item : factory_map_map) { - FactoryMap & factory_map = factory_map_item.second; - for (auto iter = factory_map.begin(); iter != factory_map.end(); ++iter) { - if (iter->second == p) { - factory_map.erase(iter); - erase_flag = true; - break; - } - } - if (erase_flag) { + for (auto & [base_class_name, factory_map] : factory_map_map) { + if (auto iter = std::ranges::find(factory_map, p, &FactoryMap::value_type::second); + iter != factory_map.end()) + { + factory_map.erase(iter); break; } } @@ -318,7 +310,7 @@ registerPlugin(const std::string & class_name, const std::string & base_class_na // Add it to global factory map map getPluginBaseToFactoryMapMapMutex().lock(); FactoryMap & factoryMap = getFactoryMapForBaseClass(); - if (factoryMap.find(class_name) != factoryMap.end()) { + if (factoryMap.contains(class_name)) { CONSOLE_BRIDGE_logWarn( "class_loader.impl: SEVERE WARNING!!! " "A namespace collision has occurred with plugin factory for class %s. " @@ -349,16 +341,16 @@ registerPlugin(const std::string & class_name, const std::string & base_class_na * by InterfaceTraits of the Base class) * @return A pointer to newly created plugin, note caller is responsible for object destruction */ -template, bool> = true> +template +requires InterfaceConstructible Base * createInstance(const std::string & derived_class_name, ClassLoader * loader, Args &&... args) { AbstractMetaObject * factory = nullptr; getPluginBaseToFactoryMapMapMutex().lock(); FactoryMap & factoryMap = getFactoryMapForBaseClass(); - if (factoryMap.find(derived_class_name) != factoryMap.end()) { - factory = dynamic_cast *>(factoryMap[derived_class_name]); + if (auto it = factoryMap.find(derived_class_name); it != factoryMap.end()) { + factory = dynamic_cast *>(it->second); } else { CONSOLE_BRIDGE_logError( "class_loader.impl: No metaobject exists for class type %s.", derived_class_name.c_str()); diff --git a/include/class_loader/interface_traits.hpp b/include/class_loader/interface_traits.hpp index f7285be..2c0b668 100644 --- a/include/class_loader/interface_traits.hpp +++ b/include/class_loader/interface_traits.hpp @@ -103,15 +103,17 @@ struct InterfaceTraits namespace impl { -template +template struct interface_constructor_parameters_impl { using type = ConstructorParameters<>; }; +// Constrained partial specialization replaces the std::void_t detection idiom: +// it is selected when InterfaceTraits defines a `constructor_parameters` member. template -struct interface_constructor_parameters_impl::constructor_parameters>> +requires requires {typename InterfaceTraits::constructor_parameters;} +struct interface_constructor_parameters_impl { using type = typename InterfaceTraits::constructor_parameters; }; @@ -190,6 +192,17 @@ template constexpr bool is_interface_constructible_v = is_interface_constructible::value; +/** + * @brief Concept satisfied when a plugin deriving from @p Base can be constructed + * from @p Args, as declared by its InterfaceTraits. + * + * Used in place of std::enable_if to constrain the create*Instance() factories, + * yielding clearer diagnostics ("constraint not satisfied") on a mismatch. + * @see is_interface_constructible + */ +template +concept InterfaceConstructible = is_interface_constructible_v; + } // namespace class_loader #endif // CLASS_LOADER__INTERFACE_TRAITS_HPP_ diff --git a/include/class_loader/multi_library_class_loader.hpp b/include/class_loader/multi_library_class_loader.hpp index 4b70fd8..a8ea70e 100644 --- a/include/class_loader/multi_library_class_loader.hpp +++ b/include/class_loader/multi_library_class_loader.hpp @@ -32,6 +32,7 @@ #ifndef CLASS_LOADER__MULTI_LIBRARY_CLASS_LOADER_HPP_ #define CLASS_LOADER__MULTI_LIBRARY_CLASS_LOADER_HPP_ +#include #include #include #include @@ -92,8 +93,8 @@ class CLASS_LOADER_PUBLIC MultiLibraryClassLoader * by InterfaceTraits of the Base class) * @return A std::shared_ptr to newly created plugin */ - template, bool> = true> + template + requires InterfaceConstructible [[nodiscard]] std::shared_ptr createInstance( const std::string & class_name, Args &&... args) { @@ -124,8 +125,8 @@ class CLASS_LOADER_PUBLIC MultiLibraryClassLoader * by InterfaceTraits of the Base class) * @return A std::shared_ptr to newly created plugin */ - template, bool> = true> + template + requires InterfaceConstructible [[nodiscard]] std::shared_ptr createInstance( const std::string & class_name, const std::string & library_path, Args &&... args) { @@ -150,8 +151,8 @@ class CLASS_LOADER_PUBLIC MultiLibraryClassLoader * by InterfaceTraits of the Base class) * @return A unique pointer to newly created plugin */ - template, bool> = true> + template + requires InterfaceConstructible [[nodiscard]] ClassLoader::UniquePtr createUniqueInstance( const std::string & class_name, Args &&... args) { @@ -180,8 +181,8 @@ class CLASS_LOADER_PUBLIC MultiLibraryClassLoader * by InterfaceTraits of the Base class) * @return A unique pointer to newly created plugin */ - template, bool> = true> + template + requires InterfaceConstructible [[nodiscard]] ClassLoader::UniquePtr createUniqueInstance( const std::string & class_name, const std::string & library_path, @@ -209,8 +210,8 @@ class CLASS_LOADER_PUBLIC MultiLibraryClassLoader * by InterfaceTraits of the Base class) * @return An unmanaged Base* to newly created plugin */ - template, bool> = true> + template + requires InterfaceConstructible [[nodiscard]] Base * createUnmanagedInstance(const std::string & class_name, Args &&... args) { ClassLoader * loader = getClassLoaderForClass(class_name); @@ -232,8 +233,8 @@ class CLASS_LOADER_PUBLIC MultiLibraryClassLoader * @param args - arguments for the constructor of the derived class (types defined * by InterfaceTraits of the Base class) */ - template, bool> = true> + template + requires InterfaceConstructible [[nodiscard]] Base * createUnmanagedInstance( const std::string & class_name, const std::string & library_path, Args &&... args) @@ -259,8 +260,7 @@ class CLASS_LOADER_PUBLIC MultiLibraryClassLoader [[nodiscard]] bool isClassAvailable(const std::string & class_name) const { std::vector available_classes = getAvailableClasses(); - return available_classes.end() != std::find( - available_classes.begin(), available_classes.end(), class_name); + return std::ranges::find(available_classes, class_name) != available_classes.end(); } /**