第一个问题是gFactory 是const&。 registerType 是非const 方法。
auto& gFactory = Factory<Widget>::getInstance();
解决这个问题。
gFactory.registerType(protoType, 32u);
registerType 期待 unique_ptr<Widget>。您正在传递 unique_ptr<Widget>,但您正在尝试复制它。
您不能复制unique_ptr。
gFactory.registerType(std::move(protoType), 32u);
接下来,这里有一个缺少的论点和类似的问题:
const auto& [iter, inserted] = mFactoryRegInfo.try_emplace(rkey, std::move(protoType));
然后你丢弃了main 中的 nodiscard 参数。
Live example.
要求ICloneable<T> 实际上被认为是泛型代码中的反模式。
template<class T, class C=std::unique_ptr<T>>
struct can_clone:std::false_type{};
template<class T>
struct can_clone<T, decltype( std::declval<T const&>().clone() )>:std::true_type {};
template <typename T,
std::enable_if_t< can_clone<T>{}, bool > = true
>
class Factory final {
public:
//! Thread safe singleton pattern
static Factory& getInstance() {
static std::unique_ptr<Factory> pInstance = std::make_unique<Factory>(token{0});
return *pInstance;
}
//! Registers a new cloneable type in the factory.
[[nodiscard]] bool registerType(std::unique_ptr<T> protoType, const uint32_t rkey) {
// Critical Section
std::lock_guard<std::mutex> lock(MutexGuard);
const auto& [iter, inserted] = mFactoryRegInfo.try_emplace(rkey, std::move(protoType));
return inserted;
}
//! Factory function - returns newly cloned unique_ptr<T>.
[[nodiscard]] std::unique_ptr<T> getClone(const uint32_t rkey) const {
// Critical Section
std::lock_guard<std::mutex> lock(MutexGuard);
const auto& iter = mFactoryRegInfo.find(rkey);
if (iter != mFactoryRegInfo.end()) {
return iter->second->clone();
}
return nullptr;
}
//! C.67: A polymorphic class should suppress copying.
Factory(const Factory&) = delete;
Factory(Factory&&) noexcept = delete;
Factory& operator=(const Factory&) = delete;
Factory& operator=(Factory&&) noexcept = delete;
//! Defaulted destructor.
~Factory() = default;
private:
//! Singleton private constructor.
Factory() = default;
struct token { explicit token(int){} };
public:
explicit Factory(token):Factory() {}
private:
// UUID (uint32_t) to T mapping
std::map<uint32_t, std::unique_ptr<T>> mFactoryRegInfo{};
mutable std::mutex MutexGuard;
};
这只是要求T 有一个支持返回unique_ptr<T> 的T::clone() const 方法。
一个改进是要求它返回一个类型可转换为 unique_ptr<T>。
另请注意,我清理了您的单例代码。请注意,您不应该将单例代码与功能代码混合在一起;从单元测试到需要特定于文档的对象工厂,有很多理由可以在同一代码库中拥有多个 Factory<Bob>。
如果需要,可以将单例实现为模板元编程的一个单独位。
当您意识到混合动态库加载时单例生命周期变得异常复杂时,这将挽救您的生命。
Live example.