问题描述
阅读 cppreference 中的摘录时
When reading the excerpt from cppreference
如果Iterator
没有五种成员类型difference_type
、value_type
、pointer
、reference
和 iterator_category
,那么这个模板没有任何这些名字的成员(std::iterator_traits
是 SFINAE 友好的)
我自动认为这意味着每个成员类型都是在迭代器本身中定义时定义的.但是你瞧,这实际上意味着如果所有五个都被定义了,那么它们就被定义了.
I automatically thought it meant each member type is defined when they are defined in the iterator itself. But lo and behold, it actually meant if all five are defined, then they are defined.
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
存储在某处而不关心其他任何事情.
Why is this? I would've thought it is friendlier if they were independent of each other. For example if an algorithm just needs to store the value_type
somewhere and doesn't care about anything else.
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;
It will fail to compile on some iterator that only defined value_type
, but funnily enough, succeed if it were instead typename It::value_type v;
推荐答案
可以从相应的提案中收集到一些见解 N3844:
Some insight can be gathered from corresponding proposal N3844:
事后看来,不时有人认为SGI STL(以及因此的 C++98)错误地指定iterator_traits 作为五个类型别名的包,并且那个个体与迭代器相关的特征会是一个更好的设计.即使是真的,本文不建议改变基本的捆绑设计,保持全有或全无的原则.
所以看起来只是尝试非常谨慎地处理当前情况并进行最小的更改以使特征SFINAE友好.选择性地包含成员会导致半定义的特征,显然,这被认为是一个潜在的深远结果.
So it looks like it was just to try to approach the current situation very cautiously and make the minimum change required to make the traits SFINAE-friendly. Selective inclusion of the member would lead to the half-defined traits, and apparently, this was considered a potentially far-reaching result.
这篇关于iterator_traits SFINAE 友好性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!