iterator_traits SFINAE 友好性 [英] iterator_traits SFINAE friendliness

查看:25
本文介绍了iterator_traits SFINAE 友好性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

阅读 cppreference 中的摘录

When reading the excerpt from cppreference

如果Iterator没有五种成员类型difference_typevalue_typepointerreferenceiterator_category,那么这个模板没有任何这些名字的成员(std::iterator_traits 是 SFINAE 友好的)

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)

我自动认为这意味着每个成员类型都是在迭代器本身中定义时定义的.但是你瞧,这实际上意味着如果所有五个都被定义了,那么它们就被定义了.

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 作为五个类型别名的包,并且那个个体与迭代器相关的特征会是一个更好的设计.即使是真的,本文不建议改变基本的捆绑设计,保持全有或全无的原则.

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. Even if true, this paper proposes no change to the basic bundled design, keeping to an all-or-nothing principle.

所以看起来只是尝试非常谨慎地处理当前情况并进行最小的更改以使特征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 友好性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆