2015-10-15 82 views
14

這裏是MCVE:簡單的std :: regex_search()代碼將不與蘋果鐺++編譯-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; 
} 

它編譯細:

$鐺++ -std = C++ 11的main.cpp

,但不與:

$鐺++ -std = C++ 14的main.cpp

錯誤後一種情況下的消息(與-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. 

編譯版本信息:

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

那麼,怎麼了?

+2

有趣的是,注意到gcc/libstdC++在C++ 11和C++ 14中都有這個失敗,這似乎是一件好事,因爲這基本上是未定義的行爲。 –

+1

你知道我幾乎可以肯定,我之前看到過這個問題:[Visual Studio regex_iterator Bug?](http://stackoverflow.com/q/29895747/1708801),雖然這是與regex_iterator/regex_token_iterator。 –

回答

9

有一個變化從C++ 11到C++ 14要去的地方std::regex_search不再允許採取一個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; 

該溶液中加入作爲取過載a const std::string&

被禁止接受臨時字符串,否則該函數會將字符串迭代器中的match_results m填充爲立即變爲無效的字符串迭代器。

所以,你不能再穿越到臨時到std::regex_search爲C++ 14

要解決你的代碼中,我們將簡單地存儲從s()返回到主變量中,並用它來打電話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

所以,我需要在main()中創建一個本地std :: sting變量,通過s()返回的內容初始化它,然後將這個變量傳遞給std :: regex_search,對吧? – Wildcat

+1

@Wildcat是的。添加回答 – NathanOliver

6

該C++ 11和C++ 14之間改變。如果我們去cppreference section for std::regex_search我們可以看到,因爲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; 

這是由於改變LWG issue 2329: regex_match()/regex_search() with match_results should forbid temporary strings它說(重點煤礦):

考慮下面的代碼:

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

這偶爾會崩潰。問題是, dir_iter-> path()。filename()。string()返回一個臨時字符串,所以 match_results包含無效的迭代器到被銷燬的 臨時字符串

regex_match/regex_search(str,reg)可以接受臨時的 字符串,因爲它們只是返回bool。 但是,採用match_results的過載應禁止臨時字符串

而事實上,如果我們使用一個非暫時性的:

std::string s1 = s() ; 

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

它編譯(see it live),不再表現出不確定的行爲。

有趣的是,注意到gcc/libstdC++在C++ 11模式下也有這個過載被刪除,以及see it live。由於這是未定義的行爲,它似乎是一個很好的解決方案。

此問題也會在圖書館的其他區域彈出,請參閱Visual Studio regex_iterator Bug?,該問題涉及相同的問題,但涉及regex_iterator/regex_token_iterator

2

這不是一個錯誤,而是預期的行爲。 原因是s()返回一個臨時字符串,regex_search使用regex_match,因此如果使用臨時字符串匹配結果將包含迭代器到一個不再存在的字符串。這將是未定義的行爲。因此,委員會取消了C++ 14中的這種重載。

您還可以確認標準28.4頭簡介[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; 

正如你所看到的,需要一個右值到basic_string被標記爲刪除過載。

相關問題