Перебор ссылок?

Я хотел бы выполнить ту же операцию на нескольких массивов, что-то вроде:

#include<vector>
#include<algorithm>
int main(void){
    std::vector<double> a, b;
    for(auto& ab:{a,b}) std::sort(ab.begin(),ab.end()); // error 
}

этот код не выполняется, так как auto& является const-ссылкой. Есть ли элегантный способ обойти это?

3 ответов


Я думаю, что проблема заключается в том, что это немного похоже привязка временных к неконстантной ссылки. Там нет" конкретной " коллекции, поэтому она немного похожа на временную.

если у вас есть временный вектор, он будет привязываться к ссылке const, но не к не-const.

Я тоже думаю, что это никогда не будет работать, что вы делаете, но это должно работать:

#include<vector> 
#include<algorithm> 
int main(void)
{     
    std::vector<double> a, b;     
    for(std::vector<double>* ab:{&a,&b}) 
      std::sort(ab->begin(),ab->end()); // or begin(*ab),end(*ab)
} 

и auto может работать тоже.


этот код не выполняется, поскольку auto& является const-ссылкой. [выделено мной]

ваши рассуждения не выдерживают критики. В цикле for на основе диапазона то, что вы объявляете (здесь,auto& ab) is не привязанные к выражению диапазона (здесь {a,b }). Вместо ab устанавливается с элементов диапазона, а не самого диапазона.

вместо этого ошибка связана с вызовом std::sort параметры ab.begin()/ab.end(), что можно легко засвидетельствовать, комментируя тело цикла. Как отметил Рмартиньо, элементы std::initializer_list<std::vector<double>> неизменяемы, и вы не можете сортировать const контейнера (std::sort перемешивает элементы с помощью ходов, не может назначить const элемент).

предполагая, что вы хотите (независимо) сортировать оба вектора, вы можете сделать:

for(auto& ab: { std::ref(a), std::ref(b) })
    std::sort(std::begin(ab.get()), std::end(ab.get()));

обратите внимание, что в соответствии с правилами вывода аргументов шаблона,auto& прекрасно здесь и auto будет вывод const std::reference_wrapper<std::vector<double>>, поддавшись std::reference_wrapper<std::vector<double>> const& тип ab.


Я думаю, что CashCows решение хорошо. Просто чтобы показать другой способ: вы также можете использовать variadic шаблоны для решения этой проблемы.

#include <vector>
#include <algorithm>

using namespace std;

void mysort() {} // termination version

template<typename Arg1, typename... Args>
void mysort(Arg1 &arg1, Args&... args )
{
    sort(arg1.begin(), arg1.end());
    mysort(args...);
}

int main(void)
{
    vector<double> a, b;
    mysort(a, b);
}

@CashCow: можно передать алгоритм в качестве аргумента, но он немного уродлив из-за использования decltype:

#include <vector>
#include <algorithm>

using namespace std;

template<typename Algo>
void mysort(Algo algo) {} // termination version

template<typename Algo, typename Arg1, typename... Args>
void mysort(Algo algo, Arg1 &arg1, Args&... args )
{
    algo(arg1.begin(), arg1.end());
    mysort(algo, args...);
}

int main(void)
{
    vector<double> a, b;
    mysort(&sort<decltype(a.begin())>, a, b);
}