繁体   English   中英

引入类型特征后非模板的模板定义

[英]Template definition of non-template after introducing typetraits

我有一个ServiceLocator类。 它工作正常,但是我想添加一个类型特征,即ServiceLocator必须使用扩展了某些BaseService类的Service-Type。 我的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:错误:非模板'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_ptrstd::unique_ptr<BaseClass>并在我的两个方法中使用static_cast 但是无法使它正常工作。 唯一需要的是类型T必须扩展我的BaseService

如果我删除模板的typetrait部分,则可以正常工作,因此,如果我删除此部分:

这本来应该是关于出了什么问题的强烈暗示(旁注:这不是类型特征,而是约束)。 问题是,您正在使用类模板声明,而忽略默认值:

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>);
    // ...
};

现在,您只有一个template参数,因此没有问题。


请注意,在C ++ 11之后,您不再需要NonCopyable ,只需显式删除特殊成员函数即可:

struct BaseService {
    BaseService() = default;
    BaseService(BaseService const&) = delete;
    BaseService& operator=(BaseService const&) = delete;
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM