微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 CRTP 时如何在下面的代码中声明变量类型 X

如何解决使用 CRTP 时如何在下面的代码中声明变量类型 X

当使用 CRTP 时,我试图根据一些配置值创建对象。 但是我不确定我在调用Factory create方法时在main方法中声明的类型应该是什么。

这是 CRTP 的基类

    template <typename TConfigurationStore>
    class ConfigManager
    {
        public:
        ConfigManager() = default;

        bool Configure(const INIReader& iniReader)
        {
            LOG(INFO) << "ConfigManager::Configure called.";
            return static_cast<TConfigurationStore*>(this)->Configure(iniReader);
        }            
    };

我们想要使用的实现。

    class RedisConfiguration : public ConfigManager<RedisConfiguration>
    {
        public:
        bool Configure(const INIReader& iniReader)
        {
            LOG(INFO) << "RedisConfiguration::Configure called";
            return true;
        }   
    };

一个实现...

    class FileConfiguration : public ConfigManager<FileConfiguration>
    {
        public:
        bool Configure(const INIReader& iniReader)
        {
            LOG(INFO) << "EmptyConfiguration::Configure called";
            return false;
        }   
    };
 class ConfigManagerFactory
    {
        public:
        template <typename TConfigurationStore>
        static ConfigManager<TConfigurationStore> *CreateConfigManager(const INIReader& iniReader)
        {
            std::string remoteConfigType = iniReader.Get("RemoteConfiguration","type","");
            if (remoteConfigType == REdis_TYPE_NAME)
            {
                return new RedisConfiguration();
            }


            return new EmptyConfiguration();;
        }

        
        private:
       
        inline static const std::string REdis_TYPE_NAME {"redis"};
        
    };

我的问题是我应该用什么来代替 X

int main()
{

X myconfmgr = ConfigManagerFactory::CreateConfigManager(iniReader);
}

解决方法

如果没有 CreateConfigManager() 的调用者以与 iniReader 相同的方式分析 CreateConfigManager(),它根本无法知道将哪个模板参数指定给 CreateConfigManager(),例如:

std::string remoteConfigType = iniReader.Get("RemoteConfiguration","type","");
if (remoteConfigType == "redis")
{
    auto myconfmgr = ConfigManagerFactory::CreateConfigManager<RedisConfiguration>(iniReader);
    myconfmgr->Configure(iniReader);
    ...
    delete myconfmgr;
}
else
{
    ...
}

调用者不必关心传入工厂的类型。这完全违背了使用工厂的初衷。

我同意@Human-Compiler 的评论。 CRTP 对于这段代码真的没有意义。简单的多态性就足够了。

去掉模板,使Configure()~ConfigManager()virtual中成为ConfigManager,在Configure()中覆盖RedisConfiguration,{{ 1}} 等。那么 FileConfiguration 可以返回一个普通的 CreateConfigManager()(或者更好的 ConfigManager*)。

试试这个:

std::unique_ptr<ConfigManager>
class ConfigManager
{
public:
    ConfigManager() = default;
    virtual ~ConfigManager() = default;

    virtual bool Configure(const INIReader& iniReader) = 0;
};

class RedisConfiguration : public ConfigManager
{
public:
    bool Configure(const INIReader& iniReader) override
    {
        LOG(INFO) << "RedisConfiguration::Configure called";
        return true;
    }   
};

class FileConfiguration : public ConfigManager
{
public:
    bool Configure(const INIReader& iniReader) override
    {
        LOG(INFO) << "EmptyConfiguration::Configure called";
        return false;
    }   
};

class ConfigManagerFactory
{
public:
    static std::unique_ptr<ConfigManager> CreateConfigManager(const INIReader& iniReader)
    {
        std::string remoteConfigType = iniReader.Get("RemoteConfiguration","");
        if (remoteConfigType == REDIS_TYPE_NAME)
        {
            return std::make_unique<RedisConfiguration>();
        }

        ...

        return std::make_unique<EmptyConfiguration>();
    }

private:
    inline static const std::string REDIS_TYPE_NAME {"redis"};        
};

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。