简体   繁体   English

iterator_traits SFINAE友好

[英]iterator_traits SFINAE friendliness

When reading the excerpt from cppreference 阅读cppreference的摘录

If Iterator does not have the five member types difference_type , value_type , pointer , reference , and iterator_category , then this template has no members by any of those names ( std::iterator_traits is SFINAE-friendly) 如果Iterator没有五个成员类型difference_typevalue_typepointerreferenceiterator_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>);
}

Live 生活

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. 例如,如果算法只需要在某处存储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;
}

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; 它将无法在仅定义value_type某些迭代器上进行编译,但有趣的是,如果它是typename It::value_type v; ,则会成功typename It::value_type v;

Some insight can be gathered from corresponding proposal N3844 : 可以从相应的提案N3844收集一些见解:

With benefit of hindsight, it has from time to time been argued that the SGI STL (and consequently C++98) erred in specifying iterator_traits as a bundle of five type aliases, and that individual iterator-related traits would have been a better design. 事后看来,它经常被认为SGI STL(以及C ++ 98)错误地将iterator_traits指定为一个包含五种类型的别名,并且单个迭代器相关的特征将是一个更好的设计。 Even if true, this paper proposes no change to the basic bundled design, keeping to an all-or-nothing principle. 即使这是真的,本文也建议不对基本的捆绑设计进行修改,保持一个全有或全无的原则。

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. 所以看起来它只是试图非常谨慎地接近目前的情况,并做出使SFINAE友好的特性所需的最小变化。 Selective inclusion of the member would lead to the half-defined traits, and apparently, this was considered a potentially far-reaching result. 选择性地包括该成员将导致半定义的特征,显然,这被认为是潜在的深远结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM