2013-08-29 15 views
4

好吧,我一直在苦苦掙扎,因爲昨天這個奇怪的錯誤,所以我想是時候讓社區...(Objective-)C++複製模板專業化符號

我目前的工作目標-C++,我有在頭文件這樣的純粹的C++類的聲明:

#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 

它的模板類,具有基本矩陣運算,但是,我要優化上T =浮子通過模板特一些瓶頸。我有包括Matrix.cpp文件,如下所示:

#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 

的問題如下: 如果我定義USE_NEON_UPSAMPLING2X =虛假和USE_NEON_THRESHOLD =真,一切工作正常 - 應用程序是建立和工作方式類似魅力。但是,如果我設置USE_NEON_UPSAMPLING2X = true,則連接斷開與以下內容:

duplicate symbol __ZNK6MatrixIfE10upsample2xEv in: 
    /.../OCRDemo-eggnlcolcwqycjagwvwddpfwgzlb/Build/Intermediates/OCRDemo.build/Release-iphoneos/OCRDemo.build/Objects-normal/armv7/A.o 
    /.../OCRDemo-eggnlcolcwqycjagwvwddpfwgzlb/Build/Intermediates/OCRDemo.build/Release-iphoneos/OCRDemo.build/Objects-normal/armv7/B.o 
duplicate symbol __ZNK6MatrixIfE10upsample2xEv in: 
    /.../OCRDemo-eggnlcolcwqycjagwvwddpfwgzlb/Build/Intermediates/OCRDemo.build/Release-iphoneos/OCRDemo.build/Objects-normal/armv7/A.o 
    /.../OCRDemo-eggnlcolcwqycjagwvwddpfwgzlb/Build/Intermediates/OCRDemo.build/Release-iphoneos/OCRDemo.build/Objects-normal/armv7/C.o 
duplicate symbol __ZNK6MatrixIfE10upsample2xEv in: 
    /.../OCRDemo-eggnlcolcwqycjagwvwddpfwgzlb/Build/Intermediates/OCRDemo.build/Release-iphoneos/OCRDemo.build/Objects-normal/armv7/A.o 
    /.../OCRDemo-eggnlcolcwqycjagwvwddpfwgzlb/Build/Intermediates/OCRDemo.build/Release-iphoneos/OCRDemo.build/Objects-normal/armv7/D.o 

有趣的是,這兩種方法都在這些文件中使用,但是連接器只抱怨upsample2x ......之間的唯一區別從語法的角度來看,這兩個參數的數量是:閾值有一個參數T,而upsample2x不需要 - 除此之外,兩者都被定義爲const,都返回矩陣等。

所以我的問題是:什麼導致這個神祕的錯誤,我該如何解決它?

+0

不要在.cpp中定義模板成員,它會對你沒有好處。 –

+0

.cpp文件僅用於從頭文件中分離實現,避免單片1000行頭文件。否則,頭文件中會包含.cpp,因此編譯器應該在其中粘貼內容。 無論如何,我用.cpp的內容替換了include指令,但結果保持不變。 (我知道你不能像正常的C++類那樣分離模板聲明和實現,但這裏不是這種情況。) –

回答

9

你的錯誤是雙重的。首先你在.cpp文件中編寫模板代碼。然後,爲了糾正這個錯誤,你將.cpp文件包含在頭文件中,這是另一個不好的主意。

爲什麼?

類模板實際上不是一個類,但只是一組類的模板。可以根據需要創建的類。另一方面,.cpp文件只編譯一次,這是不夠的,甚至沒有意義,因爲在這一點上你只有一個模板。

另一方面,要包含.cpp文件本身就是一件壞事,因爲它通常會導致重新編譯可能無法重新編譯的代碼,從而導致鏈接錯誤。

編輯:要麼你可以定義在.cpp文件中特(但不包括純粹的模板代碼,並且不包括它!),或者你可以內嵌他們,讓他們在頭:

#if USE_NEON_UPSAMPLING2X 
template<> inline Matrix<float> Matrix<float>::upsample2x() const{ 
    ... // specialized for ARM NEON float32_t 
} 
#endif 

#if USE_NEON_THRESHOLD 
template<> inline Matrix<float> Matrix<float>::threshold(float thresholdValue)const{ 
    ... // specialized for ARM NEON float32_t 
} 
+0

好吧,但是當我用include指令替換cpp文件的內容時,同樣的問題仍然存在(並完全擺脫cpp)。 –

+0

更新了我的答案。希望能幫助到你! – Naffnuff

+0

它的工作原理!很酷,儘管我不知道爲什麼:S我認爲「內聯」是編譯器通過內聯某些方法消除push/pop開銷的暗示。「inline」的用法有什麼不同? –

4

inline加到您的定義。