2016-06-05 5 views
4

Я не могу получить std :: remove_if для компиляции, как вы можете видеть. Я выбрал альтернативный метод ручного кривошипа, который отлично работает, ошибки компилятора находятся внизу базы данных после кода.STL std :: remove_if сбой компилятора

Любая помощь будет высоко оценена.

Спасибо, Том

#include <iostream> 
#include <fstream> 
#include <set> 
#include <algorithm> 
#include <string> 

// 
// Find the largest compound word composed 
// of sub-words from a list. 
// 
// - read list from file. 
// 
// Psuedo Code: 
// 
// 1. Read Next Word from File. 
// 2. Search in list for word formed from word. 
// 3. if Found in List 
// 4. if Found Compound is longer then Current Compound 
// 5.  Replace 
// 6.  Remove all strings less then Current Compound Length 
// 7. 
// 

typedef std::set<std::string> StrSet; 
typedef StrSet::iterator StrSetIter; 


struct if_substr 
{ 
    std::string m_word; 
public: 
    if_substr(const std::string& w) : m_word(w) { } 

    bool operator() (const std::string& str) const 
    { 
    std::size_t f = m_word.find(str); 
    return (std::string::npos!=f && m_word.length()>str.length()); 
    } 

}; 

struct if_remove 
{ 
    std::string m_word; 
public: 
    if_remove(const std::string& w) : m_word(w) { } 

    bool operator() (std::string str) const 
    { 
     return m_word.length()>str.length(); 
    } 

}; 


class FindLongestCompound 
{ 

    std::ifstream m_file; 

    StrSet m_words; 
    std::string m_current; 

public: 
    FindLongestCompound(std::string filename) 
    { 
    m_file.open(filename, std::ifstream::in); 

    if (!m_file) 
     throw std::runtime_error("Failed to open file"+filename); 
    } 


    void Start(void) 
    { 
    std::string nextWord; 
    while(m_file >> nextWord) 
    { 

     std::cout << "read word: " << nextWord << std::endl; 
     if_substr ifSubstr(nextWord); 
     StrSetIter srchItem = std::find_if(std::begin(m_words), std::end(m_words),ifSubstr); 
     if (srchItem != m_words.end()) 
     { 
     m_current = nextWord; 
     std::cout << "new current: " << m_current << std::endl; 


     if_remove ifRemove(m_current); 
     std::remove_if(m_words.begin(), m_words.end(),ifRemove); 

     #if 0 
     StrSetIter j = m_words.begin(); 
     do 
     { 
      if (j->length() < m_current.length()) 
      j = m_words.erase(j); 
      else 
      j++; 

     } while (j != m_words.end()); 
     #endif 
     } 
     std::cout << "insert next word: " << nextWord << std::endl; 
     m_words.insert(nextWord); 
    } 
    } 

    std::string result() { return m_current; } 

}; 


int main(int argc, char *argv[]) 
{ 
    if (argc<2) 
    { 
    std::cout << "Please provide filename" << std::endl; 
    return -1; 
    } 

    FindLongestCompound flc(argv[1]); 

    flc.Start(); 

    std::cout << "result: " << flc.result() << std::endl; 
} 
--- errors --- 
In file included from stackoverflow.C:2: 
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/iostream:38: 
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/ios:216: 
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__locale:15: 
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/string:439: 
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/algorithm:2148:26: 
error: no viable overloaded '=' 
        *__first = _VSTD::move(*__i); 
        ~~~~~~~~^~~~~~~~~~~~~~~~~~ 
    stackoverflow.C:91:8: note: in instantiation of function template specialization 
'std::__1::remove_if<std::__1::__tree_const_iterator<std::__1::basic_string<char>, 
std::__1::__tree_node<std::__1::basic_string<char>, void *> *, long>, 
if_remove>' requested here 
        std::remove_if(m_words.begin(), m_words.end(),ifRemove); 
         ^
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/string:1415:19: 
note: candidate function not viable: 'this' argument has type 'const 
value_type' (aka 'const std::__1::basic_string<char>'), but method is 
not marked const 
     basic_string& operator=(const basic_string& __str); 
        ^
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/string:1422:45: 
note: candidate function not viable: 'this' argument has type 'const 
value_type' (aka 'const std::__1::basic_string<char>'), but method is 
not marked const 
     _LIBCPP_INLINE_VISIBILITY basic_string& operator=(const value_type* __s) {return assign(__s);} 
               ^
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/string:1423:19: 
note: candidate function not viable: 'this' argument has type 'const 
value_type' (aka 'const std::__1::basic_string<char>'), but method is 
not marked const 
     basic_string& operator=(value_type __c); 
        ^
    1 error generated. 
+2

Ограничьте свою проблему. –

+1

Попробуйте создать [*** Минимальный ***, полный и проверенный пример] (http://stackoverflow.com/help/mcve). –

+1

Кроме того, если вы программируете на C++ 11, почему вы используете объекты-объекты вместо lambdas? –

ответ

6

Проблема не с функтора, но с типом контейнера, который вы используете. Вы не можете использовать std::remove_if с std::set (ваш StrSet в этом случае).

Проще говоря, std::remove_if ничего не удаляет, а только изменяет порядок элементов так, что «удаленные» элементы появляются только после определенной точки. Только erase действительно устраняет их.

A std::set, однако, имеет определенный элемент заказа, который не может быть обойден любой операцией. Допустим, вы следующий набор лексикографически упорядоченных строк:

{ "aaa", "bbb", "ccc", "ddd", "eee" } 

Теперь вы пытаетесь применить std::remove_if с функтора, который удаляет все гласного только строки. Вы закончили бы с этим:

{ "bbb", "ccc", "ddd", "aaa", "eee" } 
        ^
        | 
     "removed" elements start here 

Это работает, например. std::vector, но не с std::set, потому что это приведет к набору, элементы которого больше не упорядочены правильно («удаленные» элементы все еще являются частью набора!). Таким образом, вы получаете ошибку компиляции.

Для достижения желаемой цели используйте std::set::erase в петле. Он будет работать нормально, потому что только итераторы стираемого элемента недействительны, поэтому end() остается в силе.

if_remove ifRemove(m_current); 
for (StrSet::iterator set_iter = m_words.begin(); set_iter != m_words.end();) 
{ 
    if (ifRemove(*set_iter)) 
    { 
     set_iter = m_words.erase(set_iter); 
    } 
    else 
    { 
     ++set_iter; 
    } 
} 

В C++ 11, вы можете использовать auto вместо StrSet::iterator.

Смежные вопросы