代码之家  ›  专栏  ›  技术社区  ›  JHBonarius

冲突声明/重定义:不同的基本类型

  •  0
  • JHBonarius  · 技术社区  · 6 年前

    我正在尝试使用一个可变模板类来构建父子关系的结构。

    #include <tuple>
    
    template<typename TParentTuple, typename TChilderenTuple>
    class Obj;
    
    template<typename... TParents, typename... TChildren>
    class Obj<std::tuple<TParents...>, std::tuple<TChildren...>> {
    private:
        std::tuple<std::vector<std::shared_ptr<TParents...>>> parentsVectors;
        std::tuple<std::vector<std::shared_ptr<TChildren...>>> childrenVectors;
    };
    
    
    using Tree = Obj<std::tuple<>, std::tuple<>>;
    using Dog = Obj<std::tuple<>, std::tuple<>>;
    using Parasite = Obj<std::tuple<>, std::tuple<>>;
    
    using Human = Obj<std::tuple<>,std::tuple<Tree, Dog>>;
    using Tree = Obj<std::tuple<Human>, std::tuple<>>;
    using Dog = Obj<std::tuple<Human>, std::tuple<Parasite>>;
    using Parasite = Obj<std::tuple<Dog>, std::tuple<>>;
    
    int main() {}
    

    这在MSVS2017中给了我这种错误:

    错误C2371:“Tree”:重新定义;不同的基本类型

    在GCC中:

    错误:声明冲突

    我一直在网上寻找如何解决这个问题,但还没有找到。这个可以修吗?

    编辑:

    我什么 真正地 我想做的是使用元编程来阻止我编写大量重复的代码,就像我在中所做的那样。 this answer

    编辑2:

    好的,让我们展开。关系解释见 this question

    我一直在写 Human Dog 等课程

    人类.hpp

    #include "BaseObject.hpp"
    #include "Tree.hpp"
    #include "Dog.hpp"
    class Tree;
    class Dog;
    
    class Human : public BaseObject {
    public:
        prtVector<BaseObject> getAllParents() const override;
        prtVector<BaseObject> getAllChildren() const override;
    
        void removeAllParents() override;
        void removeAllChildren() override ;
    
        friend class Dog;
        friend class Tree;
        template<class A, class B>
        friend void addRelation(A* a, B* b);
    private:
        void addParent(Human* const);
        void removeParent(Human const* const);
        void addChild(Human* const);
        void removeChild(Human const* const);
        void addChild(Tree* const);
        void removeChild(Tree const* const);
        void addChild(Dog* const);
        void removeChild(Dog const* const);
    private:
        prtVector<Human> parents;
        prtVector<Human> children;
        prtVector<Tree> plants;
        prtVector<Dog> pets;
    };
    

    人.cpp

    #include "Human.hpp"
    
    prtVector<BaseObject> Human::getAllParents() const {
        prtVector<BaseObject> result(std::cbegin(parents), std::cend(parents));
        return result;
    }
    
    prtVector<BaseObject> Human::getAllChildren() const {
        prtVector<BaseObject> result(std::cbegin(children), std::cend(children));
        result.insert(std::end(result), std::cbegin(pets), std::cend(pets));
        result.insert(std::end(result), std::cbegin(plants), std::cend(plants));
        return result;
    }
    
    void Human::removeAllParents() {
        for (auto parent : parents) { parent->removeChild(this); }
        parents.clear();
    }
    
    void Human::removeAllChildren() {
        for (auto child : children) { child->removeParent(this); } children.clear();
        for (auto pet : pets) { pet->removeParent(this); } pets.clear();
        for (auto plant : plants) { plant->removeParent(this); } plants.clear();
    }
    
    void Human::addParent(Human* const parent) { parents.push_back(parent); }
    
    #include <algorithm>
    void Human::removeParent(Human const* const parent) {
        auto it = std::find(std::cbegin(parents), std::cend(parents), parent);
        if (it != std::cend(parents)) parents.erase(it);
    }
    void Human::addChild(Human* const child) { children.push_back(child); }
    
    void Human::removeChild(Human const* const child) {
        auto it = std::find(std::cbegin(children), std::cend(children), child);
        if (it != std::cend(children)) children.erase(it);
    }
    void Human::addChild(Dog* const pet) { pets.push_back(pet); }
    
    void Human::removeChild(Dog const* const pet) {
        auto it = std::find(std::cbegin(pets), std::cend(pets), pet);
        if (it != std::cend(pets)) pets.erase(it);
    }
    void Human::addChild(Tree* const plant) { plants.push_back(plant); }
    
    void Human::removeChild(Tree const* const plant) {
        auto it = std::find(std::cbegin(plants), std::cend(plants), plant);
        if (it != std::cend(plants)) plants.erase(it);
    }
    

    同样适用于 :狗.hpp

    #include "BaseObject.hpp"
    #include "Human.hpp"
    #include "Parasite.hpp"
    class Human;
    class Parasite;
    
    class Dog : public BaseObject {
    public:
        prtVector<BaseObject> getAllParents() const override;
        prtVector<BaseObject> getAllChildren() const override;
    
        void removeAllParents() override;
        void removeAllChildren() override;
    
        friend class Human;
        friend class Parasite;
        template<class A, class B>
        friend void addRelation(A* a, B* b);
    private:
        void addParent(Human* const);
        void removeParent(Human const* const);
        void addChild(Parasite* const);
        void removeChild(Parasite const* const);
    private:
        prtVector<Human> owners;
        prtVector<Parasite> parasites;
    };
    

    狗.cpp

    #include "Dog.hpp"
    
    prtVector<BaseObject> Dog::getAllParents() const {
        prtVector<BaseObject> result(std::cbegin(owners), std::cend(owners));
        return result;
    }
    
    prtVector<BaseObject> Dog::getAllChildren() const {
        prtVector<BaseObject> result(std::cbegin(parasites), std::cend(parasites));
        return result;
    }
    
    void Dog::removeAllParents() {
        for (auto owner : owners) { owner->removeChild(this); }
        owners.clear();
    }
    
    void Dog::removeAllChildren() {
        for (auto parasite : parasites) { parasite->removeParent(this); }
        parasites.clear();
    }
    
    void Dog::addParent(Human* const owner) { owners.push_back(owner); }
    
    #include <algorithm>
    void Dog::removeParent(Human const* const owner) {
        auto it = std::find(std::cbegin(owners), std::cend(owners), owner);
        if (it != std::cend(owners)) owners.erase(it);
    }
    
    void Dog::addChild(Parasite* const parasite) { parasites.push_back(parasite); }
    
    void Dog::removeChild(Parasite const* const parasite) {
        auto it = std::find(std::cbegin(parasites), std::cend(parasites), parasite);
        if (it != std::cend(parasites)) parasites.erase(it);
    }
    

    等等 Tree Parasite . 如你所见,里面有很多重复的代码!我在想元编程应该能够帮助我:为作为变量模板参数传递的特定类型生成函数。

    1 回复  |  直到 6 年前
        1
  •  2
  •   Frank    6 年前

    template<typename TParentTuple, typename TChilderenTuple>
    class Obj;
    
    template<typename TParents, typename TChildren>
    class Obj<std::tuple<TParents>, std::tuple<TChildren>> {};
    
    struct Human_tag {};
    struct Tree_tag {};
    struct Dog_tag {};
    struct Parasite_tag {};
    
    using Human = Obj<std::tuple<>,std::tuple<Tree_tag, Dog_tag>>;
    using Tree = Obj<std::tuple<Human_tag>, std::tuple<>>;
    using Dog = Obj<std::tuple<Human_tag>, std::tuple<Parasite_tag>>;
    using Parasite = Obj<std::tuple<Dog_tag>, std::tuple<>>;
    

    #include <tuple>
    #include <vector>
    
    template<typename TParentTuple, typename TChilderenTuple>
    class Obj;
    
    template<typename... TParents, typename... TChildren>
    class Obj<std::tuple<TParents...>, std::tuple<TChildren...>> {
    public:
      std::tuple<std::vector<typename TParents::obj_type*>...> parents_;
      std::tuple<std::vector<typename TChildren::obj_type*>...> children_;
    };
    
    struct Human_tag;
    struct Tree_tag;
    struct Dog_tag;
    struct Parasite_tag;
    
    using Human = Obj<std::tuple<>,std::tuple<Tree_tag, Dog_tag>>;
    using Tree = Obj<std::tuple<Human_tag>, std::tuple<>>;
    using Dog = Obj<std::tuple<Human_tag>, std::tuple<Parasite_tag>>;
    using Parasite = Obj<std::tuple<Dog_tag>, std::tuple<>>;
    
    struct Human_tag {
        using obj_type = Human;
    };
    struct Tree_tag {
        using obj_type = Tree;
    };
    struct Dog_tag {
        using obj_type = Dog;
    };
    struct Parasite_tag {
        using obj_type = Parasite;
    };
    
    void foo() {
        Tree t;
        Human h;
    
        std::get<0>(t.parents_).emplace_back(&h);
    }