Перебор ссылок?
Я хотел бы выполнить ту же операцию на нескольких массивов, что-то вроде:
#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);
}