多次包含名称空间的链接器错误

时间:2012-03-17 09:31:31

标签: c++ templates namespaces linker defined

我正在尝试使用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

2 个答案:

答案 0 :(得分: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.

(专业化的后一个位置是“在命名空间范围内”,例如在全局范围内,这是错误消息想要告诉你的事情。)

答案 1 :(得分:2)

功能模板的完全专业化不再是模板:它是一个功能。

因此,当您在标题中定义它时,您需要添加关键字inline

inline改变了C ++&#34;一个定义规则&#34;的行为。 (ODR)。基本上,对于inline,必须在每个使用它的翻译单元中定义该函数,并且这些定义必须实际上相等。两者都是通过将定义放在头文件中来实现的。

inline也可以作为优化提示,但第二种含义并不能保证。

另请注意,所以这个答案不会误导你,没有功能模板的部分特化。