2015-10-15 23 views
14

Đây là MCVE:Simple std :: regex_search() mã sẽ không biên dịch với Apple kêu vang ++ -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; 
} 

Nó biên dịch tốt với:

$ kêu vang ++ -std = C++ 11 main.cpp

nhưng không phải với:

$ ++ kêu vang -std = C++ 14 main.cpp

Thông báo lỗi trong trường hợp sau này (với -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 phiên bản thông tin:

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

Vì vậy, có gì sai?

+2

Điều thú vị cần lưu ý là gcc/libstdC++ có lỗi này trong cả C++ 11 và C++ 14, điều này dường như là một điều tốt vì đây là hành vi cơ bản không xác định. –

+1

Bạn biết tôi đã gần như chắc chắn tôi đã nhìn thấy vấn đề này trước khi xem: [Visual Studio regex_iterator Bug?] (Http://stackoverflow.com/q/29895747/1708801) mặc dù điều này là với regex_iterator/regex_token_iterator. –

Trả lời

9

Có một sự thay đổi đi từ C++ 11 đến C++ 14 nơi std::regex_search không còn được phép lấy một r-value

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; 

này được thêm vào như là sự quá tải mà mất a const std::string&

bị cấm chấp nhận các chuỗi tạm thời, nếu không hàm này điền match_results m với trình lặp chuỗi trở thành không hợp lệ ngay lập tức.

Vì vậy, bạn không còn có thể vượt qua một tạm thời để std::regex_search như 14

C++

Để khắc phục mã của bạn, chúng tôi sẽ chỉ đơn giản là lưu trữ sự trở lại của s() vào một biến trong chính và sử dụng để gọi 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

Vì vậy, tôi cần phải tạo một std địa phương :: sting biến trong chính(), khởi tạo nó bằng những gì được trả về bởi s(), và sau đó vượt qua biến này thành std :: regex_search, phải không? – Wildcat

+1

@Wildcat Có. Đã thêm vào câu trả lời – NathanOliver

6

này thay đổi giữa C++ 11 và C++ 14. Nếu chúng ta đi đến cppreference section for std::regex_search chúng ta có thể thấy rằng tình trạng quá tải mà phải mất một tài liệu tham khảo rvalue đã bị xóa từ 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; 

Nó được thay đổi do LWG issue 2329: regex_match()/regex_search() with match_results should forbid temporary strings mà nói (tôi nhấn mạnh):

Hãy xem xét mã sau:

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

Điều này đôi khi gặp sự cố. Vấn đề là dir_iter-> path(). Filename(). String() trả về một chuỗi tạm thời, do đó match_results chứa các trình vòng lặp không hợp lệ thành một chuỗi tạm thời bị phá hủy.

Tốt cho regex_match/regex_search (str, reg) để chấp nhận các chuỗi tạm thời, bởi vì chúng chỉ trả lại bool. Tuy nhiên, quá tải lấy match_results sẽ cấm các chuỗi tạm thời.

và thực sự nếu chúng tôi sử dụng một tổ chức phi tạm thời:

std::string s1 = s() ; 

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

nó biên dịch (see it live) và không còn thể hiện hành vi không xác định.

Thú vị lưu ý rằng gcc/libstdC++ có quá tải này bị xóa trong chế độ C++ 11 cũng như see it live. Vì đây là hành vi không xác định, nó có vẻ như là một giải pháp tốt.

Sự cố này cũng bật lên ở các khu vực khác của thư viện, xem Visual Studio regex_iterator Bug? đề cập đến cùng một vấn đề nhưng với regex_iterator/regex_token_iterator.

2

Đây không phải lỗi, nhưng hành vi mong đợi. Lý do là s() trả về một chuỗi tạm thời, regex_search sử dụng regex_match và do đó nếu một chuỗi tạm thời được sử dụng kết quả phù hợp sẽ chứa trình lặp đến một chuỗi không còn tồn tại. Đây sẽ là hành vi không xác định. Do đó, ủy ban đã bãi bỏ khoản quá tải này regex_search trong C++ 14.

Bạn cũng có thể khẳng định trong tiêu chuẩn 28.4 Tiêu đề tóm tắt [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; 

Như bạn có thể thấy sự quá tải mà phải mất một rvalue đến một basic_string được đánh dấu xóa.

Các vấn đề liên quan