2016-01-07 13 views
9

pamiętać, że jest nie duplikat z wielu pytań na StackOverflow dotycząca gcc używam Visual Studio 2013.std :: regex konstruktor zgłasza wyjątek

Ta prosta konstrukcja wyrażenia regularnego rzuca std::regex_error :

bool caseInsensitive = true; 
char pattern[] = "\\bword\\b"; 
std::regex re(pattern, std::regex_constants::ECMAScript | (caseInsensitive ? std::regex_constants::icase : 0)); 

Rzeczywisty błąd zwracany przez what na obiekcie wyjątku nie jest spójny. Zwykle jest to niedopasowana pareteza lub klamra. Czemu?

Odpowiedz

11

Problem powstaje z powodu wielu konstruktorów dostępnych dla std::regex. Śledzenie w konstruktorze pokazało to za pomocą jednego, którego nie zamierzałem!

chciałem użyć tego:

explicit basic_regex(_In_z_ const _Elem *_Ptr, 
    flag_type _Flags = regex_constants::ECMAScript) 

Ale mam ten jeden Zamiast:

basic_regex(_In_reads_(_Count) const _Elem *_Ptr, size_t _Count, 
    flag_type _Flags = regex_constants::ECMAScript) 

Trójskładnikowy wyraz w flagi powoduje typ, aby zmienić int, która nie jest zgodna flag_type w podpisie konstruktora. Ponieważ ma dopasowanie na size_t, wywołuje ten konstruktor zamiast. Flagi są źle interpretowane jako rozmiar ciągu, powodując niezdefiniowane zachowanie, gdy dostęp do pamięci za końcem łańcucha jest możliwy.

Problem nie dotyczy tylko programu Visual Studio. Udało mi się zduplikować go w gcc: http://ideone.com/5DjYiz

Można go naprawić na dwa sposoby. Pierwszy z nich to wyraźne obsada argumentu:

std::regex re(pattern, static_cast<std::regex::flag_type>(std::regex_constants::ECMAScript | (caseInsensitive ? std::regex_constants::icase : 0))); 

drugie jest uniknięcie stałych całkowitych w trójskładnikowych wyrażenie:

std::regex re(pattern, caseInsensitive ? std::regex_constants::ECMAScript | std::regex_constants::icase : std::regex_constants::ECMAScript); 
6

nie znajdę żadnej z proponowanych rozwiązań szczególnie istotnych lub estetyczne. Myślę, że wolałbym coś takiego:

auto options = std::regex_constants::ECMAScript; 
if (caseInsensitive) 
    options |= std::regex_constants::icase; 

std::regex re(pattern, options); 

Jeśli z jakiegoś powodu błędnej, naprawdę nalegać na jednej linii kodu, chciałbym użyć obiektu wartość zbudowane z odpowiedniego typu w trójskładnikowego wyrażenie:

std::regex re(pattern, std::regex_constants::ECMAScript | (caseInsensitive ? std::regex_constants::icase : std::regex_constants::std::regex_option_type{})); 

Albo, ponieważ ECMAScript jest domyślnym, należy użyć:

std::regex re(pattern, (caseInsensitive ? std::regex_constants::icase : std::regex_constants::ECMAScript)); 

przynajmniej na moje oko, to pierwszy z nich jest wyraźnie lepsze chociaż.

+0

Twoje rozwiązanie jest zdecydowanie bardziej czytelne, dzięki. –

Powiązane problemy