Ok, I have been struggling with this strange mistake since yesterday, so I think it's time to ask the community ...
I am currently working in Objective-C ++, and I have a purely cool class declaration in the header file, for example:
#ifndef __MATRIX_H__ #define __MATRIX_H__ #define USE_NEON_UPSAMPLING2X true #define USE_NEON_THRESHOLD true typedef float OCRfloat; template<class T = OCRfloat> class Matrix { public: ... Matrix threshold(T thresholdValue) const; ... Matrix upsample2x() const; ... }; #ifdef TARGET_OS_IPHONE #if USE_NEON_UPSAMPLING2X template<> Matrix<float> Matrix<float>::upsample2x() const; #endif #if USE_NEON_THRESHOLD template<> Matrix<float> Matrix<float>::threshold(float thresholdValue) const; #endif #endif #include "Matrix.cpp" #endif
This template class with basic matrix operations, however, I want to optimize some bottlenecks in the specialization of templates on T = float. I included the Matrix.cpp file as follows:
#include <iostream> #include <cmath> #if defined TARGET_OS_IPHONE #include <Accelerate/Accelerate.h> #endif ... template<class T> Matrix<T> Matrix<T>::threshold(T thresholdValue) const { ... // general naive algorithm } template<class T> Matrix<T> Matrix<T>::upsample2x() const{ ... // general naive algorithm } #ifdef TARGET_OS_IPHONE #if USE_NEON_UPSAMPLING2X template<> Matrix<float> Matrix<float>::upsample2x() const{ ... // specialized for ARM NEON float32_t } #endif #if USE_NEON_THRESHOLD template<> Matrix<float> Matrix<float>::threshold(float thresholdValue)const{ ... // specialized for ARM NEON float32_t } #endif
The problem is this: If I set USE_NEON_UPSAMPLING2X = false and USE_NEON_THRESHOLD = true, everything works fine - the application is built and works like a charm. However, if I set USE_NEON_UPSAMPLING2X = true, the linker breaks with the following:
duplicate symbol __ZNK6MatrixIfE10upsample2xEv in: /.../OCRDemo-eggnlcolcwqycjagwvwddpfwgzlb/Build/Intermediates/OCRDemo.build/Release-iphoneos/OCRDemo.build/Objects-normal/armv7/Ao /.../OCRDemo-eggnlcolcwqycjagwvwddpfwgzlb/Build/Intermediates/OCRDemo.build/Release-iphoneos/OCRDemo.build/Objects-normal/armv7/Bo duplicate symbol __ZNK6MatrixIfE10upsample2xEv in: /.../OCRDemo-eggnlcolcwqycjagwvwddpfwgzlb/Build/Intermediates/OCRDemo.build/Release-iphoneos/OCRDemo.build/Objects-normal/armv7/Ao /.../OCRDemo-eggnlcolcwqycjagwvwddpfwgzlb/Build/Intermediates/OCRDemo.build/Release-iphoneos/OCRDemo.build/Objects-normal/armv7/Co duplicate symbol __ZNK6MatrixIfE10upsample2xEv in: /.../OCRDemo-eggnlcolcwqycjagwvwddpfwgzlb/Build/Intermediates/OCRDemo.build/Release-iphoneos/OCRDemo.build/Objects-normal/armv7/Ao /.../OCRDemo-eggnlcolcwqycjagwvwddpfwgzlb/Build/Intermediates/OCRDemo.build/Release-iphoneos/OCRDemo.build/Objects-normal/armv7/Do
The funny thing is that both methods are used in these files, however, the linker only complains about upsample2x ... The only difference between them, from the syntactic point of view, is the number of arguments: the threshold has an argument from T, while upsample2x does not require any - in addition, both of them are defined as const, as return matrices, etc.
So my question is: what causes this cryptic error and how can I fix it?