我试图想象一个std::size不适合的场景std::tuple,但我却一片空白。它支持std::array,但是有它自己的size()方法,所以不需要专门化。但它也支持T[N],大概是因为它是静态大小的,即使它没有size()方法(它甚至没有std::tuple_size_v。)
那么为什么没有std::tuple得到std::size支持或方法size()呢?我什至认为也许拥有std::tuple_size_v意味着它不需要一个,但同样适用于std::array。
std::size首先,了解一些背景知识以了解Even的目的:
与迭代器是指针的泛化类似,标准容器是数组的泛化(指针是数组的迭代器)。它们都包含同类类型的元素,即所有元素都具有相同的类型,并且它们可以迭代。
与实际上满足抽象迭代器概念的指针不同,数组没有获得同样的荣誉。这可能是因为指针/迭代器的接口可以通过一些简单的运算符来满足,而容器需要使用多个函数。也许委员会更喜欢成员函数的面向对象接口,而不是数组唯一可能的自由函数。
尽管如此,编写可以通过相同接口处理数组的通用函数和类还是很有用的。虽然C++11中引入了数组包装模板(http://www.c++11.org/ std::array),它实际上是一个容器(好吧,几乎;它不满足容器需要具有的一些属性),但它不能满足所有需要重构的用例。不是一个选项(例如考虑 C 接口)。
C++11 及更高版本还引入了自由函数(模板),它们除了将调用转发到容器的相应成员函数之外什么也不做,并重载了对数组执行相同操作的模板。这些重载是通用接口,可以与模板中的数组和容器一起使用。他们是:
std::swap C++11
std::{c,}begin C++11
std::{c,}end C++11
std::size C++17
std::empty C++17
std::data C++17
Run Code Online (Sandbox Code Playgroud)
除了通用之外,std::end特别是std::size还实现了初学者容易出错的功能。
现在问题是:
为什么没有为元组定义 size/ssize (或 tuple_size_v 所在的任何地方)?
最初的提案是n4017。它不包含不支持元组的理由。我不知道委员会是否考虑过这个问题。但如果他们这样做了,因为这样的功能不在标准中,那么他们就会拒绝(至少暂时)这个想法。
元组不是容器,并且它没有成员函数size。它与容器的距离比数组远得多。至关重要的是,元组的元素是异构的;它们由不同类型的对象组成。它们不能像容器那样用迭代器进行迭代。
然而,元组可以被视为容器的更高概括。也许在遥远的将来,Boost.Fusion 将被纳入标准中,我们将拥有容器和元组的通用接口。但如果我们处于那个时间线中,那么我们仍然处于相对的过去。直到/除非它被提议并被标准接受,否则它不会发生。
奇怪的是,是和std::tuple_size之间的通用接口(但不是裸数组)。std::tuplestd::array