2013-02-12 52 views
1

我有一个模板函数,需要专门用于迭代器。所以我所做的就是沿着线:std :: iterator_traits微软标准库中的整型类型

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); 
} 

而且我碰了壁,因为微软标准库专门std::iterator_traits所有数值类型(boolcharintfloat ...)。并且它这样做使得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。
+1

另外:你的代码是无效的C++(但MSVC会接受它),你需要用'typename'标记依赖名'std :: iterator_traits :: pointer'。 – 2013-02-12 10:45:55

+0

@KonradRudolph:谢谢。我实际上在msvC++和gcc 4.5和4.6中编译,所以我需要在那里,但它不是复制粘贴;实际的代码需要一个专门处理某些事情的模板,我正在检查这个事情是否是迭代器。 – 2013-02-12 11:42:46

回答

2

其它功能[res.on.functions]

[...]

2特别地,该效果在下列情况下是未定义:

  • 用于在实例化模板组件时用作模板参数的类型,如果 类型的操作没有实现seman适用要求的子条款抽动

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

关于它的思考,因为您的评论澄清了一个合理的猜测是不够好,我想你最好使用SFINAE和enable_if检测核心业务(一元*和前缀++),使用std::iterator_traits<T>::pointer只有在这些条件满足。

+0

嗯,我怀疑任何类型都会定义':: iterator_category',而且实际上并不是迭代器,所以为了实际应用就可以了。 – 2013-02-12 10:49:34

+0

“为了使用iterator_traits ,T必须是一个迭代器” - 标准在哪里说的?算法的概念要求来自25.1/5,但我找不到任何可以说'Iterator'同样是一个特殊的模板参数名称。我同意你的看法,只是因为'iterator_traits '实例化并不意味着'T'类型是一个迭代器,所以你的答案的主要观点是无论如何。 – 2013-02-12 10:53:20

+0

我会在自己的代码中创建这样一个类型的乐趣,只是为了惹你,但那只是我。 :)是的,如果你不需要担心这种类型,你可以做一些事情。 – hvd 2013-02-12 10:53:34