美文网首页
从多类型接口到模板接口

从多类型接口到模板接口

作者: 长不胖的Garfield | 来源:发表于2018-03-30 14:24 被阅读0次

    为什么

    在一些编码实现中通常都有数据库或者属性接口,用来根据Key存取各种类型的数据,譬如:

    class OldImpl
    {
    public:
        bool has(const std::string& key) const;
    
        void setAsInt(const std::string& key, int v);
        void setAsDouble(const std::string& key, double v);
        void setAsString(const std::string& key, const std::string& v);
    
        int  asInt(const std::string& key);
        double asDouble(const std::string& key);
        std::string asString(const std::string& key);
    };
    

    实际上只有3种不同功能的接口:是否存在、读取、写入,能否将这些接口转换成对应的模板接口?

    目标

    在原有接口基础上提供模板接口,如下:

    class OldImpl
    {
    public:
        template<typename T>
        bool has(const std::string& key) const;
    
        template<typename T>
        void set(const std::string& key, const T& v);
    
        template<typename T>
        T    as(const std::string& key);
    };
    
    

    使得可以以如下方法使用:

    void test() {
        OldImpl impl;
        if (!impl.has<int>("a")) {
            impl.set<int>("a", 'a');
        }
        
        auto x = impl.as<double>("x");
        auto y = impl.as<double>("y");
        auto z = x + y;
        impl.set("z", z);
    }
    

    如何实现写入的模板接口

    首先,原有的接口是可以写成如下形式的:

        void set(const std::string& key, int v);
        void set(const std::string& key, double v);
        void set(const std::string& key, const std::string& v);
    

    这样的话写入的模板接口可以以如下方式实现:

        template<typename T>
        void set(const std::string& key, const T& v) {
            set(key, v);
        }
    

    编译时根据v的类型即可找到正确的写入接口,如果调用写入接口时指定T,可以利用C++的自动类型转换/构造来写入指定类型的值。

    如何实现读取的模板接口

    在实现写入接口时,可以根据函数参数类型的不同区分不同的接口,但是读取的模板接口仅有一个相同类型的参数,根据函数返回值是无法区分的,这时候就需要用到Tag Dispatch;
    C++是强类型语言,在名称相同的情况下,可以根据参数类型的不同来区分不同的接口;可以使用类模板定义不同的类型:

    template<typename T>
    struct TypeTag {};
    

    采用上述的方式声明类模板,那么TypeTag<int>TypeTag<double>等一系列都是不同的类型:

    这时可以将读取接口写成如下方式:

        int as(const std::string& key, TypeTag<int>);
        double as(const std::string& key, TypeTag<double>);
        std::string as(const std::string& key, TypeTag<std::string>);
    

    而读取接口模板实现如下:

        template<typename T>
        T  as(const std::string& key) {
            return as(key, TypeTag<T>());
        }
    

    如何实现是否存在接口

    通常情况下原本的has接口是直接可用的,如果需要判定某个Key及指定数据类型的值是否存在,可以参照读取接口的实现。

    学到的内容

    • Tag Dispatch

    相关文章

      网友评论

          本文标题:从多类型接口到模板接口

          本文链接:https://www.haomeiwen.com/subject/lucicftx.html