警告:不同命名空间中的模板专用化
warning: specialization of template in different namespace
使用以下代码,我得到警告:
warning: specialization of ‘template<class _Iterator> struct std::iterator_traits’ in different namespace [-fpermissive]
template<> class std::iterator_traits<Token_ptr>{
public:
typedef Word difference_type;
typedef Word value_type;
typedef Token_ptr pointer;
typedef Word& reference ;
typedef std::bidirectional_iterator_tag iterator_category ;
};
虽然一切正常,但是否有人知道发出警告的确切含义和原因。(g++发出警告,而clang++没有)。
假设您是在C++11模式下编译的(因为clang没有发出任何警告),并且这种专门化在全局命名空间中,那么您的代码就没有问题。这是一个g++错误。§14.7.3【温度解释规范】/p2:
显式专用化应在包含专用模板。明确的专业化声明符id不合格,应在模板的最近封闭命名空间中声明,或者,如果命名空间是内联的(7.3.1),来自其封闭命名空间集合的任何命名空间。这样的声明也可以是一个定义。如果声明不是定义,专业化可以稍后定义(7.3.1.2)。
全局名称空间是一个"包含专用模板的名称空间",您的声明符id是用std::
限定的,因此第二句不适用。作为一种变通方法,您可以按照cdhowie的答案进行操作,即打开一个namespace std
块并将专业化放在那里。
请参阅CWG问题374和GCC错误56480。
这里有一个可见的问题,还有一个潜在的不可见的问题。可见的问题是,此代码不在namespace std
块中。要专门化模板,您需要在所专门化的模板的名称空间内。在这种情况下,提供命名空间名称作为类型的一部分实际上并不起作用。所以你需要这样做:
namespace std
{
template<> class iterator_traits<Token_ptr>{
public:
typedef Word difference_type;
typedef Word value_type;
typedef Token_ptr pointer;
typedef Word& reference ;
typedef std::bidirectional_iterator_tag iterator_category ;
};
}
另一个潜在的问题是,该代码可能已经在另一个namespace
块中(我不知道,因为这可能不是整个源文件)。如果是,则需要首先关闭该名称空间块,这样namespace std
就不会嵌套在任何其他名称空间块中。
进一步阅读:';模板<class _Tp>structstd::less';在不同的命名空间中
- 命名空间中具有.h和.cpp文件的类
- 从父命名空间重载类型
- 在命名空间中定义函数还是限定函数
- C++:对不存在的命名空间使用命名空间指令
- 通过继承类使用来自不同命名空间的运算符
- 使用命名空间时出现多个定义错误
- GCC 和非命名空间范围内的显式专用化
- 使用类指针重载C++命名空间函数模板专用化替代方法?
- 为什么在这种特殊情况下不需要将 std::hash() 的专用化注入到 std 命名空间中?
- 非命名空间范围内的显式专用化不会在 GCC 中编译
- 不同命名空间中函数的专用化
- BGL:不同命名空间中模板的专用化
- 模板专用化/初始化和命名空间
- 命名空间中所有类的类模板专用化
- 命名空间中的函数模板专用化
- 专用模板是命名空间别名实际上是一个别名
- 在std命名空间中添加模板专用化
- 为命名空间中的类专用化方法模板
- 警告:不同命名空间中的模板专用化
- 内部结构在非命名空间作用域中的显式专用化