2

我有一些在 MSVC 下编译良好的代码(或者说是发送给我的 Windows 开发人员),但在 CLang 下会出错。环顾四周后,我发现 CLang 在解决模板专业化方面确实更加严格,但我不确定我应该将专业化放在哪里。基本上我的一个文件有一个这样的结构:

template<>
struct iterator_traits< char * >   // error is here
{
    typedef random_access_iterator_tag iterator_category;
    typedef char value_type;
    typedef ptrdiff_t difference_type;
    typedef difference_type distance_type;
    typedef char * pointer;
    typedef char & reference;
};

这是在一个namespace std块内。错误信息是:

Explicit specialization of 'std::iterator_traits<char *>' after instantiation

同一错误消息的另一部分(通过“扩展”Xcode 中的错误消息查看)说Implicit instantiation first required here,然后单击它会将我带到stl_iterator.h,特别是这一行(第 642 行):

typedef typename iterator_traits<_Iterator>::iterator_category
                                                         iterator_category;

有谁知道在这种情况下正确的做法是什么?我见过涉及类的示例,但从未见过涉及结构的示例。

4

1 回答 1

8

编译器抱怨您在实例化通用模板后尝试专门化模板 - 到那时,编译器已经使用通用模板进行实例化,它不能返回并使用您的专门化. 换句话说,是这样的:

template <typename T>
struct X
{
    // Generic implementation
};

// Instantiate template by using it in any way
X<int> foo;

template<>
struct X<int>
{
    // Specialization implementation for int
};

解决方法是在实例化之前定义特化,因此在本例中,您需要将特化移到使用X<int>where 之前X<int>

请注意,STL 已经定义了std::iterator_traitfor 指针类型的特化,因此无需在此处定义您自己的 for 特化char*。您通常只对不是指针的用户定义迭代器类型执行此操作。请参阅 C++03 标准的 §24.3.1/2:

[模板iterator_traits<Iterator>]专门用于指针

template<class T> struct iterator_traits<T*> {
  typedef ptrdiff_t difference_type;
  typedef T value_type;
  typedef T* pointer;
  typedef T& reference;
  typedef random_access_iterator_tag iterator_category;
};

和指向constas的指针

template<class T> struct iterator_traits<const T*> {
  typedef ptrdiff_t difference_type;
  typedef T value_type;
  typedef const T* pointer;
  typedef const T& reference;
  typedef random_access_iterator_tag iterator_category;
};

因此,提供自己的std::iterator_traits<char*>专业是没有意义的。由于char*不是用户定义的类型,因此根据标准它也是未定义的行为。§17.4.3.1/1 说:

std除非另有说明,否则C++ 程序将声明或定义添加到命名空间 std 或命名空间内的命名空间是未定义的。程序可以将任何标准库模板的模板特化添加到命名空间std。标准库模板的这种特化(完全或部分)会导致未定义的行为,除非声明依赖于用户定义的外部链接名称,并且除非特化满足原始模板的标准库要求。163)

163) 任何实例化其他库模板的库代码必须准备好与满足标准最低要求的任何用户提供的专业化充分合作

于 2012-10-04T16:59:20.710 回答