fuji
fuji

Reputation: 1203

c++ template function multiple instantiation

I am trying to write code to convert an opencv image to a QImage. I want to implement this as a generic function using templates. This is what I have:

#include <QImage>
#include <opencv2/core/core.hpp>

void setPixel(int j, int i, unsigned char v, QImage & img)
{
    img.setPixel(j, i, qRgb(v, v, v)); 
}        

void setPixel(int j, int i, cv::Vec3b v, QImage & img)
{
    img.setPixel(j, i, qRgb(v[2], v[1], v[0]));
}

template <typename ImageType>
QImage toQImageARGB (const cv::Mat & image)
{
    QImage res(image.cols, image.rows, QImage::Format_ARGB32_Premultiplied);
    ImageType tmp;
    for (int i = 0; i < image.rows; ++i)
    {   
        for (int j = 0; j < image.cols; ++j)
        {   
            tmp = image.at<ImageType>(i,j);
            setPixel(j, i, tmp, res); 
        }   
    }   
    return res;
}

I get the following compile time error

CMakeFiles/annotate.dir/main.cpp.o: In function `std::remove_reference<cv::ximgproc::SuperpixelSEEDS*&>::type&& std::move<cv::ximgproc::SuperpixelSEEDS*&>(cv::ximgproc::SuperpixelSEEDS*&)':
.../util.h:8: multiple definition of `setPixel(int, int, unsigned char, QImage&)'
CMakeFiles/annotate.dir/moc_widget.cxx.o:.../build/../util.h:8: first defined here
CMakeFiles/annotate.dir/main.cpp.o: In function `cv::Vec<unsigned char, 3> const& cv::Mat::at<cv::Vec<unsigned char, 3> >(int, int) const':
.../util.h:13: multiple definition of `setPixel(int, int, cv::Vec<unsigned char, 3>, QImage&)'
CMakeFiles/annotate.dir/moc_widget.cxx.o:.../build/../util.h:13: first defined here
collect2: error: ld returned 1 exit status
make[2]: *** [...] Error 1
make[1]: *** [CMakeFiles/annotate.dir/all] Error 2
make: *** [all] Error 2

from my main method.

Is it possible to do this with function templates, and does it make sense?

Upvotes: 1

Views: 289

Answers (1)

Andy Prowl
Andy Prowl

Reputation: 126542

It seems those function definitions (in particular, the two non-template overloads of setPixel()) come from a header file that gets included into more than one translation unit (i.e. .cpp file), thus violating the One Definition Rule.

If you want those functions' definitions to appear in the header file, declare them as inline:

inline void setPixel(int j, int i, unsigned char v, QImage & img)
{
    img.setPixel(j, i, qRgb(v, v, v)); 
}        

inline void setPixel(int j, int i, cv::Vec3b v, QImage & img)
{
    img.setPixel(j, i, qRgb(v[2], v[1], v[0]));
}

Upvotes: 2

Related Questions