警告:不同命名空间中的模板专用化

warning: specialization of template in different namespace

本文关键字:专用 命名空间 警告      更新时间:2023-10-16

使用以下代码,我得到警告:

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';在不同的命名空间中