2015-06-28 28 views
2

我想對子字符串進行to_upper()調用,從而傳入一個範圍。我不明白爲什麼我不能在string上構建一個範圍,但可以用相同的方式在vector上構建範圍。與std :: string一起使用make_iterator_range

使用的Xcode 6.3.2使用編譯器選項-std=c++11和Boost 1.58

void string_test() { 
    std::string my_str = "Hello, world, it's a wonderful day";  
    std::vector<int> x = {1,2,3,4,5,6,6,8,9,10}; 
    const auto rng = boost::make_iterator_range(x.begin(),x.end()-5); 
    const auto rng2 = boost::make_iterator_range(my_str.begin(),my_str.begin()+10); 
    // How do I get to_upper_copy to accept the range returned above 
    std::cout << boost::to_upper_copy(rng2) << std::endl; 

} 

我得到一個錯誤在Xcode:

/usr/local/Cellar/boost/1.58.0/include/boost/range/iterator_range_core.hpp:215:11: No matching constructor for initialization of 'std::__1::__wrap_iter<char *>' 
+1

'我不能在字符串上構建一個範圍'什麼阻止了你?當你嘗試時會發生什麼? –

回答

2

錯誤沒有任何與創建iterator_rangestring;如果您將電話註釋爲to_upper_copy,則您的代碼將被編譯。同樣,如果您將stringvector<char>(或甚至vector<int>)互換,則對to_upper_copy的調用將再次無法編譯時會出現類似的錯誤。

顯然,罪魁禍首是to_upper_copy,看着函數模板的簽名告訴我們爲什麼。

template<typename SequenceT> 
SequenceT to_upper_copy(const SequenceT &, 
         const std::locale & = std::locale()); 

你不可錯過的一對string::iterator s,這是你的make_iterator_range通話基本上是返回,因爲SequenceT因爲會有的算法沒有簡單的方法來建立一個新的SequenceT給一對迭代。這在Boost documentation中也有描述:

另外一些算法對字符串類型有附加要求。特別是,算法需要創建一個給定類型的新字符串。在這種情況下,要求該類型滿足(標準§23.1.1)的要求。

在參考和代碼中,字符串類型的要求由模板參數的名稱指定。 RangeT表示基本範圍要求必須成立。 SequenceT表示擴展序列要求

請注意,上面提到的部分來自C++ 03標準。在C++ 11和更高版本的文檔中,相關部分是§23.2.3[sequence.reqmts]。因此,iterator_range不符合SequenceT的要求。如果您將my_str改爲to_upper_copy,則代碼將進行編譯。但是,如果只想轉換子字符串,則需要創建一個包含該字符串的string,然後致電to_upper

std::cout << boost::to_upper_copy(my_str) << std::endl; // works, but not a sub-string 

std::string substr(rng2.begin(), rng2.end()); 
boost::to_upper(substr); 
std::cout << substr << std::endl; 

您還可以避免通過使用過載to_upper_copy接受一個輸出迭代參數構建中間子串。

std::string result; 
result.reserve(rng2.size()); 
boost::to_upper_copy(std::back_inserter(result), rng2); 
std::cout << result << std::endl; 

Live demo

+0

我在同一時間寫了我的答案,得出了同樣的結論;儘管我通過轉換爲矢量以不同的方式解決了這個問題。然而,這導致了單獨的SO問題 – Ronnie

+0

@Ronnie我只是想到了避免構建子字符串的替代實現。查看更新的答案。 – Praetorian

0

我終於在@實現禁衛軍的回答,您可以通過使用重載to_upper_copy()傳遞的輸出迭代器徹底清除小串分配或載體拷貝。

void string_algo() { 
    const std::string my_str = "Hello, world, it's a wonderful day"; 
    const auto rng2 = boost::make_iterator_range(my_str.begin(),my_str.begin()+10); 
    boost::to_upper_copy(rng2.begin(),rng2); 
    std::cout << rng2 << std::endl; 
} 
相關問題