基于范围的 for 带大括号初始化器而不是非常量值?

2024-05-01

我正在尝试迭代一些std::lists,对它们中的每一个进行排序。这是天真的方法:

#include<list>
using namespace std;
int main(void){
    list<int> a,b,c;
    for(auto& l:{a,b,c}) l.sort();
}

生产

aa.cpp:5:25: error: no matching member function for call to 'sort'
        for(auto& l:{a,b,c}) l.sort();
                             ~~^~~~
/usr/bin/../lib64/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/bits/stl_list.h:1586:7: note: 
      candidate function not viable: 'this' argument has type 'const
      std::list<int, std::allocator<int> >', but method is not marked const
      sort();
      ^
/usr/bin/../lib64/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/bits/stl_list.h:1596:9: note: 
      candidate function template not viable: requires 1 argument, but 0 were
      provided
        sort(_StrictWeakOrdering);
        ^
1 error generated.

我是否正确地猜测大括号初始化程序正在创建这些列表的副本?有没有办法不复制它们,并使它们在循环内可修改? (除了制作指向它们的指针列表,这是我当前的解决方法)。


你猜对了。std::initializer_list元素总是const(这使得sort()荷兰国际集团不可能,因为sort()是一个非const成员函数)及其元素总是被复制(这将使sort()- 即使它们没有意义,它们也毫无意义const)。来自 [dcl.init.list],强调我的:

类型的对象std::initializer_list<E>从初始化列表构造,就像实现一样 分配了一个由 N 个类型元素组成的临时数组const E,其中 N 是元素的数量 初始化列表。该数组的每个元素是复制初始化与初始化器的相应元素 列表,以及std::initializer_list<E>构造对象来引用该数组。[ Note:构造函数 或为副本选择的转换函数应在初始化程序的上下文中可访问(第 11 条) 列表。——尾注]如果需要缩小转换来初始化任何元素,则该程序是 格式不正确。[ 例子:

struct X {
    X(std::initializer_list<double> v);
};
X x{ 1,2,3 };

初始化的实现方式大致相当于:

const double __a[3] = {double{1}, double{2}, double{3}};
X x(std::initializer_list<double>(__a, __a+3));

假设该实现可以构造一个initializer_list带有一对指针的对象。-结尾 例子 ]

没有办法使它们成为非 const 或非复制的。指针解决方案的工作原理:

for (auto l : {&a, &b, &c}) l->sort();

因为它是pointer那是 const,而不是它指向的元素。另一种选择是编写一个可变参数函数模板:

template <typename... Lists>
void sortAll(Lists&&... lists) {
    // before C++17
    using expander = int[];
    expander{0, (void(lists.sort()), 0)...};

    // C++17 or later
    (lists.sort(), ...);
}

sortAll(a, b, c);

我想,您还可以编写一个助手将您的列表包装到一个数组中reference_wrapper to list<int>(因为你不能有一组引用),但这可能更令人困惑而不是有帮助:

template <typename List, typename... Lists>
std::array<std::reference_wrapper<List>, sizeof...(Lists) + 1>
as_array(List& x, Lists&... xs) {
    return {x, xs...}; 
}

for (list<int>& l : as_array(a, b, c)) {  // can't use auto, that deduces
    l.sort();                             // reference_wrapper<list<int>>,
}                                         // so would need l.get().sort()
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于范围的 for 带大括号初始化器而不是非常量值? 的相关文章

随机推荐