Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Specialization of template in different namespace

I'm developing a cross-platform library using C++. MSVC compiles fine but g++ is giving me problems. Suppose I have the following Enum helper class:

// File: Enum.h
#ifndef ENUM_H
#define ENUM_H

#include <map>
#include <cstring>
namespace MyLib {

#define DECLARE_ENUM( type ) template<> std::map<const char*, type>  \
            MyLib::Enum<type>::mMap = std::map<const char*, type>(); \
            template<> MyLib::Enum<type>::Enum (void)

template <typename Type> class Enum
{
private:
    Enum (void);

public:
    static int Size (void) { /* ... */ return 0; }

private:
    static std::map<const char*, Type> mMap;
};

}
#endif

Here is the intended use:

// SomeFile.cpp
#include "Enum.h"

enum MyEnum
{
    value1, value2, value3,
};

DECLARE_ENUM (MyEnum)
{
    mMap["value1"] = value1;
    mMap["value2"] = value2;
    mMap["value3"] = value3;
}

void SomeFunc (void)
{
    cout << Enum<MyEnum>::Size();
}

g++ gives me a "Specialization of template in different namespace" error. Wrapping the DECLARE_ENUM block in namespace MyLib solves this problem. My question is why do I have to do this and is there another way of fixing this that doesn't require me to add a namespace MyLib around the block?

like image 756
Dave Avatar asked Aug 14 '14 15:08

Dave


People also ask

Can you template a namespace?

The new entity that is proposed in this paper is called a namespace template. It is a template used to create one or more namespaces. A usage of that template would be a “namespace template instantiation” which is a namespace.

What is the specialty of a template function give example?

Template in C++is a feature. We write code once and use it for any data type including user defined data types. For example, sort() can be written and used to sort any data type items. A class stack can be created that can be used as a stack of any data type.

Is specialization of template C++?

The act of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation. The definition created from a template instantiation is called a specialization.


1 Answers

This changed in C++11 as a result of CWG issue 374 and N3064. The current wording (§14.7.3 [temp.expl.spec]/p2) is:

An explicit specialization shall be declared in a namespace enclosing the specialized template. An explicit specialization whose declarator-id is not qualified shall be declared in the nearest enclosing namespace of the template, or, if the namespace is inline (7.3.1), any namespace from its enclosing namespace set.

Since your declarator-id is in fact qualified with MyLib::, and the global namespace is a "namespace enclosing the specialized template", this looks like a GCC bug (bug 56480). Your code compiles fine with clang in C++11 mode.

In C++98, however, the specialization must be put inside namespace in which the template is a member (see Mark B's comment below), and clang will produce a warning if put in C++98 mode.

like image 172
T.C. Avatar answered Oct 16 '22 17:10

T.C.