0

I'm trying to fix an "explicit specialization in non-namespace scope" error using the method described in this post. So I managed to move the templated functions into a separate namespace, and I'm calling these functions from my class (see the code below).

The code now compiles, however I'm getting linker errors " already defined in main.obj" for all the functions in the namespace. I thought that adding #ifndef STYLE_H at the top would prevent the namespace from being included multiple times or am I missing something? How can I fix this error?

Below is my code (simplified):

#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
Community
  • 1
  • 1
laurent
  • 88,262
  • 77
  • 290
  • 428

2 Answers2

2

Regarding the original error,

I'm trying to fix an "explicit specialization in non-namespace scope" error

What that error means is that you cannot define member function template specializations inside a class definition. I.e. the following would be illegal:

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

However, this is solved by simply placing the specialisation outside the class definition:

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

(The latter position of the specialization is "at namespace scope", for example at global scope, which is what the error message wanted to tell you to do.)

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
2

A full specialization of a function template is no longer a template: it is a function.

As such, when you define it in a header, you need to add the keyword inline.

inline changes the behavior of C++'s "One Definition Rule" (ODR). Essentially, with inline the function must be defined in every translation unit where it’s used, and those definitions must be effectively equal. Both accomplished by placing the definition in a header file.

inline also serves as a hint about optimization, but that second meaning is not guaranteed.

Also note, so this answer does not mislead you, there is no such thing as a partial specialization of a function template.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331