2012-03-17 51 views
0

我試圖使用this post中描述的方法修復「非命名空間範圍中的顯式專用化」錯誤。所以我設法將模板化的函數移動到一個單獨的名稱空間中,並從我的類中調用這些函數(請參閱下面的代碼)。多次包含名稱空間的鏈接程序錯誤

代碼現在編譯,但是我得到了名稱空間中所有函數的「main.obj中已經定義的鏈接器錯誤」。我認爲在頂部添加#ifndef STYLE_H會阻止命名空間被多次包含,或者我錯過了什麼?我該如何解決這個錯誤?

下面是我的代碼(簡化):

#ifndef STYLE_H 
#define STYLE_H 

namespace hanzi { 

namespace styleUtil { 

    template <class T> 
    T get(const QString& name, T defaultValue = T(), const Style* style = NULL, const Style* baseStyle = NULL) {  
     // ... 
    } 

    template <> 
    QColor get<QColor>(const QString& name, QColor defaultValue, const Style* style, const Style* baseStyle) { 
     // ... 
    } 

    template <> 
    ImagingEffect get<ImagingEffect>(const QString& name, ImagingEffect defaultValue, const Style* style, const Style* baseStyle) { 
     // ... 
    } 

} 

class Style : public QObject { 

    Q_OBJECT 

public: 

    explicit Style(const QString& filePath); 

    template <class T> 
    T get(const QString& name, T defaultValue = T()) const { 
     return styleUtil::get<T>(name, defaultValue, this, baseStyle_); 
    }; 

}; 

} 

#endif // STYLE_H 
+0

錯誤中的「名稱空間」一詞並不意味着您的想法。相反,您應該將其讀爲「您無法將特化添加到類定義」。 – 2012-03-17 09:33:40

+0

@Laurent你是否錯過了Style的前瞻性聲明? – selalerer 2012-03-17 09:41:28

回答

2

對於原來的錯誤,

我試圖解決一個 「非命名空間範圍明確的專業化」 的錯誤

這個錯誤意味着你不能在類定義中定義成員函數模板特化。即以下將是非法的:

struct Bar 
{ 
    template <typename T> void boo() { } 
    // template <> void boo<char>() { boo<int>(); } // Error! Cannot specialize here 
}; 

然而,這是通過簡單地將專業化類定義解決:

template <> void Bar::boo<char>() { boo<int>(); } // Good. 

(專業化的後一位置是「在命名空間範圍」 ,例如在全球範圍內,這是錯誤信息要告訴你做的事情。)

2

函數模板的完全特化不再是一個模板:它是一個函數。

因此,當您在標題中定義它時,您需要添加關鍵字inline

inline改變了C++的「一個定義規則」(ODR)的行爲。從本質上講,使用inline時,必須在每個翻譯單元中定義該函數,並且這些定義必須實際上相同。兩者都通過將定義放在頭文件中完成。

inline也可作爲優化的提示,但不保證第二個含義。

另外請注意,所以這個答案不會誤導你,沒有這樣的東西作爲函數模板的部分專業化。

相關問題