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?
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With