2015-10-15 18 views
14

Oto MCVE:Proste std :: regex_search() kod nie zostanie skompilowany z Apple brzękiem ++ -std = C++ 14

#include <iostream> 
#include <regex> 

std::string s() 
{ 
    return "test"; 
} 

int main() 
{ 
    static const std::regex regex(R"(\w)"); 
    std::smatch smatch; 

    if (std::regex_search(s(), smatch, regex)) { 
     std::cout << smatch[0] << std::endl; 
    } 

    return 0; 
} 

To kompiluje dobrze z:

$ brzękiem ++ -std = C++ 11 main.cpp

ale nie z:

$ dzyń ++ -std = C++ 14 main.cpp

Komunikat o błędzie w drugim przypadku (z -std = C++ 14):

main.cpp:14:9: error: call to deleted function 'regex_search' 
    if (std::regex_search(s(), smatch, regex)) { 
     ^~~~~~~~~~~~~~~~~ 
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/regex:5998:1: note: 
     candidate function [with _ST = std::__1::char_traits<char>, _SA = std::__1::allocator<char>, 
     _Ap = std::__1::allocator<std::__1::sub_match<std::__1::__wrap_iter<const char *> > >, _Cp = 
     char, _Tp = std::__1::regex_traits<char>] has been explicitly deleted 
regex_search(const basic_string<_Cp, _ST, _SA>&& __s, 
^ 
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/regex:2876:5: note: 
     candidate function [with _ST = std::__1::char_traits<char>, _SA = std::__1::allocator<char>, 
     _Ap = std::__1::allocator<std::__1::sub_match<std::__1::__wrap_iter<const char *> > >, _Cp = 
     char, _Tp = std::__1::regex_traits<char>] 
    regex_search(const basic_string<_Cp, _ST, _SA>& __s, 
    ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/regex:2851:5: note: 
     candidate template ignored: deduced conflicting types for parameter '_Bp' 
     ('std::__1::basic_string<char>' vs. 'std::__1::match_results<std::__1::__wrap_iter<const char 
     *>, std::__1::allocator<std::__1::sub_match<std::__1::__wrap_iter<const char *> > > >') 
    regex_search(_Bp, _Bp, const basic_regex<_Cp, _Tp>&, 
    ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/regex:2857:5: note: 
     candidate template ignored: could not match 'const _Cp *' against 'std::string' (aka 
     'basic_string<char, char_traits<char>, allocator<char> >') 
    regex_search(const _Cp*, const _Cp*, 
    ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/regex:2863:5: note: 
     candidate template ignored: could not match 'const _Cp *' against 'std::string' (aka 
     'basic_string<char, char_traits<char>, allocator<char> >') 
    regex_search(const _Cp*, match_results<const _Cp*, _Ap>&, const basic_regex<_Cp, _Tp>&, 
    ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/regex:2869:5: note: 
     candidate template ignored: could not match 'basic_regex' against 'match_results' 
    regex_search(const basic_string<_Cp, _ST, _SA>& __s, 
    ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/regex:5963:1: note: 
     candidate template ignored: could not match 'const _CharT *' against 'std::string' (aka 
     'basic_string<char, char_traits<char>, allocator<char> >') 
regex_search(const _CharT* __str, const basic_regex<_CharT, _Traits>& __e, 
^ 
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/regex:2839:5: note: 
     candidate function template not viable: requires at least 4 arguments, but 3 were provided 
    regex_search(_Bp, _Bp, match_results<_Bp, _Ap>&, const basic_regex<_Cp, _Tp>&, 
    ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/regex:2845:5: note: 
     candidate function template not viable: requires at least 4 arguments, but 3 were provided 
    regex_search(const _Cp*, const _Cp*, match_results<const _Cp*, _Ap>&, 
    ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/regex:2884:5: note: 
     candidate function template not viable: requires at least 4 arguments, but 3 were provided 
    regex_search(__wrap_iter<_Iter> __first, 
    ^
1 error generated. 

Compiler informacje o wersji:

$ clang++ -v 
Apple LLVM version 7.0.0 (clang-700.0.72) 
Target: x86_64-apple-darwin15.0.0 
Thread model: posix 

Co jest nie tak?

+2

warto zauważyć, że gcc/libstdC++ ma ten rygorem zarówno w C++ 11 i C++ 14, który wydaje się dobrym rozwiązaniem, ponieważ jest to zasadniczo niezdefiniowane zachowanie. –

+1

Wiesz, że byłem prawie pewien, że widziałem ten problem przed zobaczeniem: [Visual Studio regex_iterator Bug?] (Http://stackoverflow.com/q/29895747/1708801) chociaż jest to z regex_iterator/regex_token_iterator. –

Odpowiedz

9

Nastąpiła zmiana począwszy od C++ C++ 11 do 14, gdzie std::regex_search nie jest już dozwolone wziąć wartość R

template< class STraits, class SAlloc, 
      class Alloc, class CharT, class Traits > 
bool regex_search(const std::basic_string<CharT,STraits,SAlloc>&&, 
        std::match_results< 
         typename std::basic_string<CharT,STraits,SAlloc>::const_iterator, 
         Alloc>&, 
        const std::basic_regex<CharT, Traits>&, 
        std::regex_constants::match_flag_type flags = 
         std::regex_constants::match_default) = delete; 

ten został dodany jako przeciążenia, które odbywają const std::string&

zabrania się przyjmowania tymczasowych ciągów, w przeciwnym razie funkcja ta zapełnia match_results m z iteratorów smyczkowych, które stają się nieważne natychmiast.

Więc nie można już przejść do std::regex_search tymczasowy jako C++ 14

naprawić swój kod chcemy po prostu zapisać powrót z s() do zmiennej w głównym i używać, aby zadzwonić std::regex_search.

#include <iostream> 
#include <regex> 

std::string s() 
{ 
    return "test"; 
} 

int main() 
{ 
    static const std::regex regex(R"(\w)"); 
    std::smatch smatch; 

    auto search = s(); 
    if (std::regex_search(search, smatch, regex)) { 
     std::cout << smatch[0] << std::endl; 
    } 

    return 0; 
} 

Live Example

+1

Muszę więc utworzyć lokalną zmienną std :: sting w main(), zainicjować ją przez to, co zwraca s(), a następnie przekazać tę zmienną do std :: regex_search, prawda? – Wildcat

+1

@Wildcat Tak. Dodano do odpowiedzi – NathanOliver

6

Zmieniło między C++ 11 i C++ 14. Jeśli idziemy do cppreference section for std::regex_search widzimy, że przeciążenie, że trwa odniesienie rvalue został usunięty ponieważ C++ 14:

template< class STraits, class SAlloc, 
      class Alloc, class CharT, class Traits > bool regex_search(const std::basic_string<CharT,STraits,SAlloc>&&, 
        std::match_results< 
         typename std::basic_string<CharT,STraits,SAlloc>::const_iterator, 
         Alloc 
        >&, 
        const std::basic_regex<CharT, Traits>&, 
        std::regex_constants::match_flag_type flags = 
         std::regex_constants::match_default) = delete; 

został zmieniony ze względu na LWG issue 2329: regex_match()/regex_search() with match_results should forbid temporary strings który mówi (podkr):

Rozważmy następujący kod:

const regex r(R"(meow(\d+)\.txt)"); 
smatch m; 
if (regex_match(dir_iter->path().filename().string(), m, r)) { 
    DoSomethingWith(m[1]); 
} 

To czasami awarii. Problemem jest to, że dir_iter-> ścieżka(). Nazwa pliku(). String() zwraca ciąg czasowy, tak się match_results zawiera unieważnione iteratory do zniszczony tymczasowego ciąg.

To jest w porządku dla regex_match/regex_search (str, reg), aby zaakceptować tymczasowe ciągi znaków , ponieważ po prostu zwracają wartość bool. Jednak przeciążenia przyjmujące wyników dopasowań powinny zabraniać tymczasowych ciągów znaków.

a nawet jeśli używamy niebędącego tymczasowa:

std::string s1 = s() ; 

if (std::regex_search(s1, smatch, regex)) { 
//... 
} 

kompiluje (see it live) i nie wykazuje niezdefiniowanej zachowanie.

Interesujące, że gcc/libstdC++ ma to przeciążenie usunięte w trybie C++ 11 oraz see it live. Ponieważ jest to niezdefiniowane zachowanie, wydaje się dobrym rozwiązaniem.

Ten problem pojawia się również w innych obszarach biblioteki, patrz Visual Studio regex_iterator Bug?, który dotyczy tego samego problemu, ale z regex_iterator/regex_token_iterator.

2

To nie jest błąd, ale oczekiwane zachowanie. Powodem jest to, że s() zwraca tymczasowy łańcuch, regex_search wykorzystuje regex_match a co za tym idzie, czy tymczasowy łańcuch został wykorzystany wyników będzie zawierać iteratory do łańcucha, który już nie istnieje. Byłoby to niezdefiniowane zachowanie. Tak więc komitet zniósł to przeciążenie w C++ 14.

Można również potwierdzić w standardowym 28,4 Nagłówek streszczenia [re.syn]:

template <class ST, class SA, class Allocator, class charT, class traits> 
bool regex_search(const basic_string<charT, ST, SA>&&, 
match_results< 
typename basic_string<charT, ST, SA>::const_iterator, 
Allocator>&, 
const basic_regex<charT, traits>&, 
regex_constants::match_flag_type = 
regex_constants::match_default) = delete; 

Jak widać przeciążenie, że trwa rvalue do basic_string jest oznaczony jako usunięte.