0

I have the following problem in my project that contains several modules (I am sorry but I could not find a simpler example) :

  • Module1 defines a full template class ILocatable
  • Module2 defines a class Component
  • Module3 defines a class LocatableEntity that inherits from ILocatable < MyVector3D> (here, MyVector3D is an std::array<double,3>)
  • Module4a uses modules 1,2,3, and defines a class LocatableComponent4a which inherits from Component and ILocatable < MyVector3D > that uses LocatableEntity
  • Module4b uses modules 1,2,3,4a, a defines a class LocatableComponent4b which inherits from Component and ILocatable < MyVector3D > and uses LocatableComponent4a and LocatableEntity

Module1 and Module3 are static libraries. Module2, Module4a, Module4b are shared libraries. All modules compile fine except Module4b where I get the following error (with Visual C++, not with Linux/GCC) :

Project5_Module4a.lib(Project5_Module4a.dll) : error LNK2005: "public: virtual __cdecl Project5::Module1::ILocatable<class std::array<double,3> >::~ILocatable<class std::array<double,3> >(void)" (??1?$ILocatable@V?$array@N$02@std@@@Module1@Project5@@UEAA@XZ) déjà défini(e) dans Project5_Module3.lib(LocatableEntity.obj)

Please not that in Debug mode, there are more duplicate symbols (one for each method of ILocatable)

How can I cope with this ? When Module3 is linked dynamically the problem disappears, but I really would like to keep the static libraries. I also tried to instanciate the template with std::array<double,3> in Module3 but :

  • This didn't solve my problem
  • Most of the users of my project shall use other instanciations, such as Eigen::Vector3d or osg::Vec3d or whatever.

Many thanks for any help !!!

The full project is available here : https://ufile.io/1tkrt6d6 (needs CMake). Here are some parts of code :

    namespace Module1 {
        template <class Vector3D>
        class ILocatable {
        protected:
            inline ILocatable() {
                this->position[0] = 0.0; this->position[1] = 0.0; this->position[2] = 0.0;
                this->frame = Frame::WGS84;
            }
        public:
            virtual inline ~ILocatable() {}
            inline const Vector3D& getPosition() const { return this->position; }
            inline void setPosition(const Vector3D& value) { this->position = value; }
            inline Frame getFrame() const { return this->frame; }
            inline void setFrame(Frame value) { this->frame = value; }
        private:
            Vector3D position;
            Frame frame;
        };
    } // namespace Module1
    namespace Module3 {
        typedef std::array<double, 3> MyVector3D;
        class Project5_Module3_EXPORT LocatableEntity : public Module1::ILocatable<MyVector3D> {
        public:
            LocatableEntity();
            virtual ~LocatableEntity();
        };
    } // namespace 
    namespace Module4a {
        typedef std::array<double, 3> MyVector3D;
        class Project5_Module4a_EXPORT LocatableComponent4a : public Module2::Component, public Module1::ILocatable<MyVector3D> {
        public:
            LocatableComponent4a();
            virtual ~LocatableComponent4a();
            void move() {
                Module3::LocatableEntity locatableEntity;
                locatableEntity.setPosition(this->getPosition());
                locatableEntity.setFrame(this->getFrame());
                Module3::move(locatableEntity);
                this->setPosition(locatableEntity.getPosition());
                this->setFrame(locatableEntity.getFrame());
            }
        };
    } // namespace Module4a
    namespace Module4b {
        typedef std::array<double, 3> MyVector3D;
        class Project5_Module4b_EXPORT LocatableComponent4b : public Module2::Component, public Module1::ILocatable<MyVector3D> {
        public:
            LocatableComponent4b();
            virtual ~LocatableComponent4b();
            void move();
            void join(const Module4a::LocatableComponent4a& otherComponent) {
                this->setPosition(otherComponent.getPosition());
                this->setFrame(otherComponent.getFrame());
            }
        };
    } // namespace Module4b
4

0 回答 0