使用以下代码我会收到警告:
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 ++没有)。
答案 0 :(得分:17)
假设你是在C ++ 11模式下编译它(因为clang没有发出警告)并且这个特化是在全局命名空间中,那么你的代码没有任何问题。这是一个g ++错误。 §14.7.3[temp.expl.spec] / p2:
应在包含的名称空间中声明显式特化 专业模板。一个明确的专业化 declarator-id 不合格,应在模板的最近的封闭命名空间中声明,或者,如果命名空间是内联的 (7.3.1),来自其封闭命名空间集的任何命名空间。这样的 声明也可以是一个定义。如果声明不是 定义,专业化可以在以后定义(7.3.1.2)。
全局命名空间是“包含专用模板的命名空间”,而您的 declarator-id 符合std::
,因此第二句不适用。作为一种解决方法,您可以执行cdhowie的答案建议 - 即打开namespace std
块并将专业化放在那里。
答案 1 :(得分:7)
这里有一个明显的问题,一个潜在的隐形问题。可见问题是此代码不在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
不嵌套在任何其他命名空间块中。
进一步阅读:Specialization of 'template<class _Tp> struct std::less' in different namespace