Search code examples
c++compiler-errorsheaderundefined-reference

Undefined reference when compiling when using header and cpp file with templates in one of them


I've been trying to compile my project and I've encountered some problems when trying so. The error in particular that appears is:

[build] /usr/bin/ld: CMakeFiles/robot_control.dir/main.cpp.o:(.data.rel.ro._ZTVN4comm15cameraInterfaceE[_ZTVN4comm15cameraInterfaceE]+0x10): undefined reference to `comm::Interface<cv::Mat>::callbackMsg()'

My project is organized right now as it follows:

-${HOME_WORKSPACE}
 |-main.cpp 
 |-src
   |-communication.cpp
   |-communication.hpp

The header file (communication.hpp) is:

#include <opencv2/opencv.hpp>
#include <gazebo/gazebo_client.hh>
#include <gazebo/msgs/msgs.hh>
#include <gazebo/transport/transport.hh>
#include <algorithm>

#ifndef COMM_GUARD
#define COMM_GUARD

namespace comm
{
    struct lidarMsg
    {
        float angle_min, angle_increment, range_min, range_max;
        int nranges, nintensities;
        std::vector<int> ranges;
    };

    template <typename T>
    class Interface
    {
        public:
            Interface() : received{false} {};

            virtual void callbackMsg();

            bool receptionAccomplished()
            {
                return this -> received;
            }
            
            T checkReceived()
            {
                return this -> elementReceived;
            }
        
        protected:
            bool received;
            T elementReceived;

    };

    class cameraInterface : public Interface<cv::Mat>
    {
        public:
            void callbackMsg(ConstImageStampedPtr &msg);
    };

    class lidarInterface : public Interface<lidarMsg>
    {
        public:
            void callbackMsg(ConstLaserScanStampedPtr &msg);
    };
}

#endif

The source file (communication.cpp) is:

#include <opencv2/opencv.hpp>
#include <algorithm>
#include <iostream>
#include "communication.hpp"

#ifndef COMM_CPP_GUARD
#define COMM_CPP_GUARD

namespace comm
{

    void cameraInterface::callbackMsg(ConstImageStampedPtr &msg)
    {
        std::size_t width = msg->image().width();
        std::size_t height = msg->image().height();
        const char *data = msg->image().data().c_str();
        cv::Mat im(int(height), int(width), CV_8UC3, const_cast<char *>(data));
        im = im.clone();
        cv::cvtColor(im, im, cv::COLOR_RGB2BGR);

        this->elementReceived = im;
        received = true;
    }

    void lidarInterface::callbackMsg(ConstLaserScanStampedPtr &msg) {

        this->elementReceived.angle_min = float(msg->scan().angle_min());
        this->elementReceived.angle_increment = float(msg->scan().angle_step());
        this->elementReceived.range_min = float(msg->scan().range_min());
        this->elementReceived.range_max = float(msg->scan().range_max());
        this->elementReceived.nranges = msg->scan().ranges_size();
        this->elementReceived.nintensities = msg->scan().intensities_size();

        for (int i = 0; i < this->elementReceived.nranges; i++)
        {
            if (this->elementReceived.ranges.size() <= i)
            {
                this->elementReceived.ranges.push_back(std::min(float(msg->scan().ranges(i)), this->elementReceived.range_max));
            }
            else
            {
                this->elementReceived.ranges[i] = std::min(float(msg->scan().ranges(i)), this->elementReceived.range_max);
            }
        }
    }
}

#endif

The main file(main.cpp) includes the following header:

#include <gazebo/gazebo_client.hh>
#include <gazebo/msgs/msgs.hh>
#include <gazebo/transport/transport.hh>
#include <opencv2/opencv.hpp>
#include <opencv2/calib3d.hpp>
#include <iostream>
#include <stdlib.h>

#include "src/communication.hpp"

I included the part of the #ifndef /#define /#endif since it is a solution that I found to this kind of problem in other problem. I've been toggling the CMakeLists.txt file but still no solution that could solve this error.


Solution

  • You can't do this:

            virtual void callbackMsg();
    

    You have to actually provide the implementation for all template methods within the .h file.