Ошибки компоновщика для пространства имен включаются несколько раз - PullRequest
0 голосов
/ 17 марта 2012

Я пытаюсь исправить ошибку «явная специализация в области, не связанной с пространством имен», используя метод, описанный в в этом посте .Поэтому мне удалось переместить шаблонные функции в отдельное пространство имен, и я вызываю эти функции из своего класса (см. Код ниже).

Код теперь компилируется, однако я уже получаю ошибки компоновщика "определено в 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 ]

2 голосов
/ 17 марта 2012

Полная специализация шаблона функции больше не является шаблоном: это функция.

Таким образом, когда вы определяете его в заголовке, вам нужно добавить ключевое слово inline.

inline изменяет поведение C ++ "One Definition Rule" (ODR). По сути, с inline функция должна быть определена в каждой единице перевода, где она используется, и эти определения должны быть фактически равны. И то, и другое достигается размещением определения в заголовочном файле.

inline также служит намеком на оптимизацию, но это второе значение не гарантируется.

Также обратите внимание, что этот ответ не вводит вас в заблуждение, нет такой вещи, как частичная специализация шаблона функции.

2 голосов
/ 17 марта 2012

Что касается исходной ошибки,

Я пытаюсь исправить ошибку "явной специализации в области, не связанной с пространством имен"

Что означает, что выне может определить специализации шаблона функции-члена внутри определения класса.Т.е. следующее было бы недопустимым:

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.

(последняя позицияспециализация - «в области имен», например, в глобальной области, что и было указано в сообщении об ошибке.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...