泛型C ++类的非侵入式设计

时间:2017-04-28 17:11:13

标签: c++ templates

使用C ++ 14,模板和Bridge模式,我试图创建一种将对象添加到名为Shapes(Shape对象的向量)的容器的通用方法。我希望能够自动支持添加到容器中的新数据类型并打印它们,而无需修改Shape类的原始实现。相反,我想只提供一个新的打印(T)功能,一切都应该是开箱即用的。

下面是我的代码,我仍然有一些问题需要编译。有人可以帮帮我吗?非常感谢。

#include <iostream>
#include <memory>
#include <vector>
#include <map>
#include <string>

using namespace std;

void print(const int toPrint) {
    cout << " " << toPrint;
    cout << endl;
}

void print(const double toPrint) {
    cout << " " << toPrint;
    cout << endl;
}

void print(const vector<int> & toPrint) {
    for (auto & it : toPrint) {
        cout << " " << it;
    }
    cout << endl;
}

void print(const map<int, string> & toPrint) {
    for (auto & it : toPrint) {
        cout << "     " << it.first << " : " << it.second << endl;
    }
    cout << endl;
}

class Shape {
public:
    template<typename T>
    Shape(T &&t) {
        pimpl_ = make_unique<Specialization<T>>(t);
    }
    void print() const {
        pimpl_->print();
    }
private:
    struct Base {
        virtual void print() const = 0;
        virtual ~Base() = default;
    };

    template<typename T>
    struct Specialization: public Base {
        Specialization(T &t) :
                internalObject_ { std::move(t) } {
        }
        void print() const override {
            ::print(internalObject_);
        }

        T internalObject_;
    };

    unique_ptr<Base> pimpl_; 

};

typedef vector<Shape> Shapes;

void print(Shapes const & shapes) {
    for (auto & shape : shapes) {
        shape.print();
    }
}

int main() {
    Shapes shapes;

    shapes.push_back(1);
    shapes.push_back(2.0);
    shapes.push_back(0.3);

    shapes.push_back(vector<int> { 10, 11, 12 });
    shapes.push_back(map<int, string> { { 0, "elmo" }, { 1, "leom" } });

    print(shapes);
    return 0;
}

1 个答案:

答案 0 :(得分:2)

以下是编译的代码的补丁版本(在clang上)。正如评论中指出的那样,有几个问题需要解决(例如,此代码会泄漏内存),但这应该会让您回到正轨。

#include <iostream>
#include <vector>

using namespace std;

void print(int toPrint) {
    cout << " " << toPrint;
    cout << endl;
}

void print(double toPrint) {
    cout << " " << toPrint;
    cout << endl;
}

void print(vector<int> toPrint) {
    for (auto & it : toPrint) {
        cout << " " << it;
    }
    cout << endl;
}

class Shape {
public:
    template<typename T>
    Shape(T t) {
        pimpl_ = new Specialization<T>(t);
    }
    void print() const{
        pimpl_->print();
    }
private:
    struct Base {
        virtual void print() const = 0;
    };

    template<typename T>
    struct Specialization: public Base {
        Specialization(T t) {
            internalObject_ = new T(t);
        }
        void print() const{
            ::print(*internalObject_);
        }

        T* internalObject_;
    };

    Base * pimpl_;
};

typedef vector<Shape> Shapes;

void print(Shapes const & shapes) {
    for (auto & shape : shapes) {
        shape.print();
    }
}

int main() {
    Shapes shapes;

    shapes.push_back(1);
    shapes.push_back(2.0);
    shapes.push_back(0.3);

    shapes.push_back(vector<int> { 10, 11, 12 });
    print(shapes);
    return 0;
}