1

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

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 标准库专门std::iterator_traits用于所有数字类型(bool, char, int, float...)。并且它是这样做的reference并且pointer是非void的,尽管事实上在这些类型上既不能调用operator*也不能调用。operator->

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

但是,我有兴趣知道:

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

1 回答 1

2

其他功能 [res.on.functions]

[...]

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

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

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

考虑一下,由于您的评论澄清了合理的猜测就足够了,我认为您最好使用 SFINAE 并enable_if检测核心操作(一元*和前缀++),std::iterator_traits<T>::pointer仅在满足这些条件时使用。

于 2013-02-12T10:35:26.500 回答