0

我正在尝试使用本文中描述的方法修复“非命名空间范围内的显式专业化”错误。所以我设法将模板化函数移动到一个单独的命名空间中,并从我的类中调用这些函数(参见下面的代码)。

代码现在可以编译,但是对于命名空间中的所有函数,我收到“已经在 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
4

2 回答 2

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.

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

于 2012-03-17T09:42:27.377 回答
2

函数模板的完全特化不再是模板:它是一个函数。

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

inline改变了 C++ 的“一个定义规则”(ODR)的行为。本质上,inline必须在使用该函数的每个翻译单元中定义该函数,并且这些定义必须有效地相等。两者都是通过将定义放在头文件中来完成的。

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

另请注意,因此此答案不会误导您,没有函数模板的部分专业化之类的东西。

于 2012-03-17T09:43:09.200 回答