为什么我们不能通过索引访问元组的元素?

anu*_*kul 18 c++ stl

tuple <int, string, int> x=make_tuple(1, "anukul", 100);
cout << x[0];       //1
cout << get<0>(x);  //2
Run Code Online (Sandbox Code Playgroud)

2件作品.1没有.

为什么会这样?

从Lounge C++我了解到这可能是因为编译器不知道该索引存储的数据类型.但它对我来说没有多大意义,因为编译器可以只查找该元组的声明并确定数据类型,或者在通过索引访问其他数据结构元素时执行其他任何操作.

gal*_*tte 33

因为[]是一个运算符(已命名operator[]),因此是一个成员函数,并在运行时调用.

获取元组项是模板机制,而它必须在编译时解析.这意味着只能使用<>模板语法完成此操作.

为了更好地理解,元组可以存储不同的类型.模板函数可能会返回不同的类型,具体取决于传递的索引,因为这是在编译时解决的.无论传递的参数的值是什么,operator []必须返回唯一类型.因此,元组功能是不可实现的.

get<0>(x)并且get<1>(x)是在编译时生成的两个不同的函数,并返回不同的类型.编译器实际上会生成两个函数,这些函数将被修改为类似的东西

int get_tuple_int_string_int_0(x)
Run Code Online (Sandbox Code Playgroud)

string get_tuple_int_string_int_1(x)
Run Code Online (Sandbox Code Playgroud)


Leu*_*nko 13

这里的其他答案解决了为什么无法实现这一问题的问题,但也值得问一下它是否应该可行的问题.(答案是不.)

下标运算符[]在语义上应该表示对集合元素的动态解析访问,例如数组或列表(任何实现).访问模式通常意味着某些事情:周围代码可能不知道元素的数量,正在访问的元素可能在运行时变化,并且元素都是相同的可观察类型(因此,对于调用代码) ,可互换的).

事实上,元组不是(那种)集合.它实际上是一个匿名的struct,它的元素根本不是可互换的插槽 - 从语义上讲,它们是常规字段.什么是可能扔你离开是他们碰巧用数字来标示,但是这真的只是一个匿名的命名模式-类似于访问元素x._0,x._1等.(你可以计算的字段名称,这一事实在编译时是一个巧合由C++的类型系统启用的奖励,并没有从根本上与元组是什么有关;元组和这个答案并不是真正特定于C++.)

因此它不支持operator[]普通旧结构不支持的相同原因operator[]:在此上下文中没有语义有效的用法.结构具有一组固定的字段,这些字段不可互换或可动态计算,并且由于元组结构而不是集合,因此它遵循相同的规则.它的字段名称看起来不同.

  • 类型理论上,元组和记录都是产品类型,唯一的区别是记录的组件被标记,而元组则不标记.所以,是的,一个元组与一个`struct`(这就是C++如何拼写"记录")与匿名字段几乎完全相同. (3认同)

Ton*_*roy 5

operator[]鉴于您无法改变静态返回类型以匹配所访问的元素,因此它不是非常干净的支持.如果标准库包含类似boost::any或类似的内容boost::variant,那将更有意义.

换句话说,如果你写的东西如下:

int n = atoi(argv[1]);
int x = x[n];
Run Code Online (Sandbox Code Playgroud)

那么,如果n没有解决一个int成员的问题该tuple怎么办呢?为了支持检查,您需要为tuples 存储某种方式的RunTime类型信息,这是可执行文件/内存中的额外开销.

  • @AnukulSangwan:不 - "auto"必须能够在编译时计算出特定的类型,因此它知道要为对象保留多少内存,要求析构函数调用等等. (3认同)

mpa*_*ark 5

它可以被支持,它只需要一个编译时索引。由于无法创建函数的参数constexpr,因此我们需要将索引包装在类型中,然后传递给它。(例如std::integral_constant<std::size_t, N>

以下是std::tuple该支持的扩展operator[]

template <typename... Ts>
class tuple : public std::tuple<Ts...> {
  public:
  using std::tuple<Ts...>::tuple;

  template <std::size_t N>
  decltype(auto) operator[](std::integral_constant<std::size_t, N>) {
    return std::get<N>(*this);
  }
};
Run Code Online (Sandbox Code Playgroud)

它的用法如下:

tuple<int, std::string> x(42, "hello");
std::cout << x[std::integral_constant<std::size_t, 0>{}] << std::endl;
// prints: 42
Run Code Online (Sandbox Code Playgroud)

为了减轻std::integral_constant疯狂,我们可以使用变量模板:

template <std::size_t N>
std::integral_constant<std::size_t, N> ic;
Run Code Online (Sandbox Code Playgroud)

这样,我们可以说:

std::cout << x[ic<1>] << std::endl;  // prints: hello
Run Code Online (Sandbox Code Playgroud)

因此可以做到。关于为什么当前不可用的一个猜测是因为引入了诸如std::integral_constant和可变模板之类的功能std::tuple。至于为什么即使这些功能存在也不存在,我想这是因为还没有人提出它。