Is for (auto i: unordered_map) гарантированно имеет одинаковый порядок каждый раз?

Когда я перебираю по std::unordered_map с диапазоном, основанным на цикле в два раза, гарантирован ли порядок равным?

std::unordered_map<std::string, std::string> map;

std::string query = "INSERT INTO table (";
bool first = true;
for(auto i : map)
{
    if(first) first = false;
    else query += ", ";
    query += i.first;
}
query += ") ";

query += "VALUES (";
first = true;
for(auto i : map)
{
    if(first) first = false;
    else query += ", ";
    query += i.second;
}
query += ");"

В приведенном выше примере результирующая строка должна быть в этой форме. Поэтому важно, чтобы оба раза, порядок итераций один и тот же.

INSERT INTO table (key1, key2, key3) VALUES (value1, value2, value3);

Гарантируется ли это на С++?

Ответ 1

Порядок итераций неупорядоченных ассоциативных контейнеров может быть изменен только при повторном использовании в результате операции мутирования (как описано в С++ 11 23.2.5/8). Вы не изменяете контейнер между итерациями, поэтому порядок не изменится.

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

Ответ 2

Почему бы не собрать их вместе?

for(auto i : map)
{
    if(first) first = false;
    else{
        keys += ", ";
        query += ", ";
    }
    keys += i.first;

    values += i.second;
}

std::string query = "INSERT INTO table (" + keys + ") VALUES (" + values ")";

Выглядит лучше имо.

Обратите внимание, что если этот раздел критичен по производительности, вы можете рассмотреть возможность оптимизации процесса построения строк с помощью std:: stringstream, как показано здесь, хотя это не ясно, сколько может помочь