2015-04-27 3 views
8

Я на Visual Studio 2013, и я вижу, что я думаю, это ошибка, я надеялся, что кто-то сможет подтвердить это?Ошибка Visual Studio regex_iterator?

string foo{ "A\nB\rC\n\r" }; 
vector<string> bar; 

for (sregex_iterator i(foo.cbegin(), foo.cend(), regex("(.*)[\n\r]{1,2}")); i != sregex_iterator(); ++i){ 
    bar.push_back(i->operator[](1).str()); 
} 

Этот код поражает Debug Утверждение в библиотеке Visual Studio регулярное выражение:

regex_iterator сиротой

Если я определяю regex вне for -loop это прекрасно:

string foo{ "A\nB\rC\n\r" }; 
vector<string> bar; 
regex bug("(.*)[\n\r]{1,2}"); 

for (sregex_iterator i(foo.cbegin(), foo.cend(), bug); i != sregex_iterator(); ++i){ 
    bar.push_back(i->operator[](1).str()); 
} 

В качестве альтернативы это работает отлично в преобразование, как показано в this question:

string foo{ "A\nB\rC\n\r" }; 
vector<string> bar; 

// This puts {"A", "B", "C"} into bar 
transform(sregex_iterator(foo.cbegin(), foo.cend(), regex("(.*)[\n\r]{1,2}")), sregex_iterator(), back_inserter(bar), [](const smatch& i){ return i[1].str(); }); 

Может кто-то подтвердить это ошибка?

ответ

10

В C++ 11 вы можете привязать временный regex к const regex &, который может привести к неопределенному поведению, если итератор используется вне времени жизни временного объекта, так как он сохранит указатель на него. Это дефект в спецификации, и это не ошибка, хотя Visual Studio ловит это с помощью отладки assert.

sregex_iterator i(foo.cbegin(), foo.cend(), regex("(.*)[\n\r]{1,2}")) 
              ^^^^^ 
              temporary 

Следующая Исключен перегрузка добавлял в C++ 14, чтобы предотвратить этот случай, от cppreference:

regex_iterator(BidirIt, BidirIt, 
      const regex_type&&, 
      std::regex_constants::match_flag_type = 
      std::regex_constants::match_default) = delete;  (since C++14) 

, и он говорит:

Перегрузка 2 не допускается вызывать с временным регулярным выражением, , поскольку возвращенный итератор будет немедленно аннулирован.

Так это не Visual Studio ошибка, поскольку она реализует стандарт C++ 11, и это не было адресовано через отчет дефектной до позже. Оба clang и gcc использование -std=c++14 или больше будет выдавать ошибку с первым (see it live) и третий (see it live). Например, Visual Studio только начал поддерживать некоторые C++ 14 в VS 2015:.

[...] и начальная поддержка для некоторых C++ 14 функций [...]

Мы можем видеть, что LWG defect 2332: regex_iterator/regex_token_iterator should forbid temporary regexes занимается этим:

Пользователи могут написать "для (sregex_iterator я (s.begin(), s.end(), регулярное выражение (" мяу ")), конец; я = конец; ++ i) ", привязывая временное регулярное выражение к const regex & и сохраняя точку к нему. Это будет автоматически компилироваться, запускает неопределенное поведение во время выполнения. Теперь у нас есть технология , чтобы предотвратить ее компиляцию, например, как reference_wrapper отказывается от привязываться к временным.

As T.C. указывает, что последний пример, который вы показываете, на самом деле нормально, хотя вы привязываете его к временному, его время жизни продолжается до конца выражения.

+0

Итак, что вы говорите, это тот факт, что он скомпилирован, является ошибкой? И факт, что я мог бы сделать заявление 'transform', - ошибка? –

+3

@JonathanMee: тот факт, что он скомпилирован, означает, что VS 2013 в основном пытается реализовать C++ 11, а не C++ 14. Тот факт, что 'transform' работал, на самом деле не является ошибкой. Вы использовали временную информацию после ее уничтожения. Это неопределенное поведение, поэтому компилятор может сделать что-либо * и по-прежнему соответствовать стандарту. –

+0

@JerryCoffin Интересно, я думаю, это проблема не в полной поддержке какого-либо стандарта. Я определенно предположил, что конструктор перемещения будет висеть на 'regex'. –

2

Нет, это не ошибка. См. LWG 2329 regex_match()/regex_search() with match_results should forbid temporary strings. Эта конструкция демонстрирует неопределенное поведение, поскольку она связывает временное регулярное выражение с константным regex & и сохраняет указатель на него.

Также см. C++14 STL Features, Fixes, And Breaking Changes In Visual Studio 14 CTP1, где это указано как исправление.

+0

Обратите внимание, что LWG 2329 - это временная '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ''. Вы ищете [LWG 2332] (http://cplusplus.github.io/LWG/lwg-defects.html#2332). Если реализация Visual Studio LWG 2332 действительно удалила конструктор 'move' для' regex', он не должен был компилироваться. –