我有一个 ServiceLocator
类(class)。它工作正常,但我想添加一个类型特征,即 ServiceLocator
必须使用扩展某些 BaseService
的服务类型类(class)。我的BaseService
类有一些我希望每个服务都拥有的属性,比如不可复制。那么让我们看看我的代码:
#pragma once
#include <memory>
#include <type_traits>
#include "BaseService.hpp"
template <typename T, typename std::enable_if<std::is_base_of<BaseService, T>::value>::type* = nullptr>
class ServiceLocator {
private:
ServiceLocator() {}
static std::unique_ptr<T> service;
public:
static void provide(std::unique_ptr<T> service) {
ServiceLocator::service = std::move<>(service);
}
static T &getService() {
return *(ServiceLocator::service.get());
}
};
template <typename T>
std::unique_ptr<T> ServiceLocator<T>::service;
这段代码并不那么神奇。但是我收到以下错误:
ServiceLocator.hpp:22:39: error: template definition of non-template ‘std::unique_ptr<_Tp>ServiceLocator::service’ std::unique_ptr ServiceLocator::service;
就像我说的,我的 BaseService
类不是那么特别,但为了完整性:
#pragma once
#include "NonCopyable.hpp"
class BaseService : private NonCopyable {
};
不可复制:
#pragma once
class NonCopyable {
public:
NonCopyable() {}
private:
NonCopyable(const NonCopyable&) = delete;
NonCopyable& operator=(const NonCopyable&) = delete;
};
如果我删除模板的类型特征部分,它会起作用,所以如果我删除这部分:
, typename std::enable_if<std::is_base_of<BaseService, T>::value>::type* = nullptr
我试图制作 unique_ptr
固定类型:std::unique_ptr<BaseClass>
并与 static_cast
一起工作在我的两种方法中。但无法让它发挥作用。
唯一需要的是类型 T
必须延长我的 BaseService
.
最佳答案
It is working if i remove the typetrait part of my template, so if i remove this part:
这应该是一个关于问题的强烈提示(旁注:这不是类型特征,而是约束)。问题是,你的类模板声明是忽略默认值:
template <typename T, typename std::enable_if<std::is_base_of<BaseService, T>::value>::type*>
class ServiceLocator { ... };
也就是说,它有两个模板参数:一个类型,一个非类型。您的课外静态定义是:
template <typename T>
std::unique_ptr<T> ServiceLocator<T>::service;
这是一个模板参数。那不是一回事。您不能在此处依赖默认值,因为还需要为非默认情况定义静态成员。
这里的解决方案只是将您的约束移动到正文中 - 因为作为模板参数,我认为它不会为您解决任何问题:
template <typename T>
class ServiceLocator {
static_assert(std::is_base_of_v<BaseService, T>);
// ...
};
现在您只有一个模板参数,所以没问题。
请注意,在 C++11 之后,您不再需要 NonCopyable
,您可以显式删除特殊成员函数:
struct BaseService {
BaseService() = default;
BaseService(BaseService const&) = delete;
BaseService& operator=(BaseService const&) = delete;
};
关于c++ - 引入typetraits后非模板的模板定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49492555/