Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redeclaration error for a templated function

Tags:

c++

templates

I have a setup where a templated function is inheriting another templated function.

template <typename DataType>
class ClassBase
{ 
  virtual void InitModel(const cv::Mat& data) {};
}

template <typename DataType>
class ClassDerived : public ClassBase<DataType>
{
  void InitModel(const cv::Mat& data) {};
}

Now I try to implement two specializations and one general templating for InitModel in ClassDerived in an implementation file

template<>
void ClassDerived<float>::InitModel(const cv::Mat& data)
{
 // initialize some things
}

template<>
void ClassDervied<cv::Vec3b>::InitModel(const cv::Mat& data)
{
  // initialize some things
}

template<typename DataType>
void ClassDerived<DataType>::InitModel(const cv::Mat& data)
{
  // initialize some things
}

Before I wrote this, I did not have any specializations and it was working fine. As soon as I added specialization, I get an error saying there was a redeclaration of the specification function. The weird part is that the redeclaration points out to the same line no. in the same file. Since it was working fine before specialization, I expect the file isn't being read twice.

So, why would such an error start popping up as soon as the specializations are added ?

The error is :

/other/workspace/perception/perception_kit/object_detection/include/perception_kit/object_detection/grimson_GMM_templated_impl.tpp:129: multiple definition of `perception_kit::GrimsonGMMGen::InitModel(cv::Mat const&)' CMakeFiles/test_obj.dir/src/object_detection_templated_test_platform.cpp.o:/other/workspace/perception/perception_kit/object_detection/include/perception_kit/object_detection/grimson_GMM_templated_impl.tpp:129: first defined here

Is the problem because I am trying to derive a templated class or something else ?

Now I understand that for some, it might be a trivial problem but I have spent considerable time before I posted it here.

The base class is in BaseClass.h (its implemented as an abstract class) The derived class declaration is in DerivedClass.h The derived class declaration is in DerivedClass.tpp and is included in DerivedClass.h

like image 790
navderm Avatar asked Jul 05 '26 20:07

navderm


2 Answers

You already defined the base template code inline in the header (with an empty body) so you can't redefine it again later. I suspect that's the source of your problem here, NOT the specializations.

like image 164
Mark B Avatar answered Jul 07 '26 09:07

Mark B


You need to declare that you have specializations for those types. Otherwise, when the compiler in a different translation unit instantiates the template it will generate code for the member functions based on the primary template. When you try to link those generated functions with your specializations the linker will see multiple definitions of the specializations.

// Header
template <typename T>
struct test {
   void f() {}
};
template <>
void test<int>::f();       // Declare the specialization

// Implementation (cpp, not included by client code)
template <>
void test<int>::f() { ... }

Note that function specializations are no longer templates, but regular functions. If different translation units include the definition of the function, then they will generate the code in multiple translation units. If you want to do that, then you can skip the declaration of the specialization and provide the definition directly, but you will need to make it inline:

// Implementation (if in header/included by user code)
template <>
inline void test<int>::f() { ... }
like image 35
David Rodríguez - dribeas Avatar answered Jul 07 '26 09:07

David Rodríguez - dribeas



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!