std::iterator_traits用于Microsoft标准库中的积分类型

std::iterator_traits for integral types in Microsoft standard library

本文关键字:类型 Microsoft iterator traits 用于 std 标准      更新时间:2023-10-16

我有一个模板函数,它需要专门用于迭代器。所以我所做的是:

template <typename T>
void function2(T whatever, typename std::iterator_traits<T>::pointer) // ... iterator
template <typename T>
void function2(T whatever, ...) // ... non-iterator
template <typename T>
void function(T whatever) {
    function2(whatever, NULL);
}

我遇到了一堵墙,因为Microsoft标准库专门为所有数字类型(boolcharintfloat…)提供std::iterator_traits。它这样做使得referencepointer是非void,尽管事实上operator*operator->都不能在这些类型上调用。

好的,我可以检查std::iterator_traits<T>::category是否以一些更复杂的模板机制为代价导出std::input_iterator(实际上我认为std::forward_iterator在我的情况下更合适)。

然而,我有兴趣知道:

  • 为什么他们为不符合迭代器概念的类型定义iterator_traits(即使输出迭代器至少需要一元operator*,这些类型都没有
  • 他们这样做是否违反了C++规范?并不是说微软不会到处违反它,但如果他们违反了,我会对编译器特定的解决方案感到满意,如果他们显然没有
  • 总的来说,它可行吗?std::iterator_traits<T>::pointer似乎总是存在,但未定义,这会导致错误,而不是SFINAE

其他功能[res.on.functions]

[…]

2特别是,在以下情况下,影响是不明确的:

  • 对于在实例化模板组件时用作模板参数的类型,如果该类型不实现适用的"需求"子条款的语义

为了使用iterator_traits<T>T必须是迭代器。如果不是,则行为是未定义的。在编译时无法检测类型T是否是迭代器。这在理论上甚至是不可能的,因为一个类型被允许支持与迭代器相同的运算符和typedef,因此实现的泛型iterator_traits<T>可以在没有任何错误或警告消息的情况下实例化,但具有完全不同的含义。

仔细想想,由于您的评论阐明了合理的猜测就足够了,我认为您最好使用SFINAE和enable_if来检测核心操作(一元*和前缀++),只有在满足这些条件的情况下才使用std::iterator_traits<T>::pointer