从cppreference读取节选时
如果
Iterator没有五个成员类型(difference_type、value_type、pointer、reference和iterator_category),那么这个模板就没有这些名称的成员(std::iterator_traits是SFINAE友好的)。
我认为这意味着在迭代器本身中定义每个成员类型时都会定义它们。但是瞧,这实际上意味着,如果所有的五个都被定义了,那么它们就被定义了。
struct defined
{
using difference_type = int;
using value_type = int;
using pointer = int*;
using reference = int&;
using iterator_category = std::input_iterator_tag;
};
struct undefined
{
using value_type = int;
};
template<typename T>
using value_type = typename std::iterator_traits<T>::value_type;
void foo()
{
using std::experimental::is_detected_v;
static_assert(is_detected_v<value_type, defined>);
static_assert(!is_detected_v<value_type, undefined>);
}为什么会这样呢?如果他们彼此独立的话,我会觉得他们更友好。例如,如果一个算法只需要在某个地方存储value_type,而不关心其他任何事情。
template<typename It>
auto amazingfy(It first, It last)
{
typename std::iterator_traits<It>::value_type v;
for(; first != last; first++)
v += *first;
return v;
}它将无法在只定义value_type的迭代器上编译,但有趣的是,如果它是typename It::value_type v;,则会成功。
发布于 2018-03-13 16:19:06
可以从相应的提案N3844中获得一些见解。
事后看来,人们不时会认为,STL (以及由此产生的C++98)错误地将iterator_traits指定为一个由五种类型别名组成的包,而单个迭代器相关的特性将是一个更好的设计。即使是真的,这篇论文也不建议改变基本的捆绑设计,坚持要么全是要么全无的原则。
所以看起来,它只是试图非常谨慎地接近目前的情况,并作出最低限度的改变,以使特性SFINAE友好。有选择地加入该成员将导致半定义的特征,显然,这被认为是一个潜在的深远的结果。
https://stackoverflow.com/questions/49260285
复制相似问题