2013-12-10 3 views
1

Ошибка:станд :: for_each + функтор дает непонятную ошибку

g++ -c -g -O0 -fno-strict-aliasing --std=c++11 -I/home/chap/private/WDI/git -I/home/chap/private/WDI/git/include -I/usr/include/mysql -fno-strict-aliasing tom.cpp 
In file included from /usr/include/c++/4.7/algorithm:63:0, 
       from /usr/include/boost/optional/optional.hpp:19, 
       from /usr/include/boost/optional.hpp:15, 
       from /usr/include/boost/format/internals.hpp:20, 
       from /usr/include/boost/format.hpp:38, 
       from tom.h:16, 
       from tom.cpp:1: 
/usr/include/c++/4.7/bits/stl_algo.h: In instantiation of ‘_Funct std::for_each(_IIter, _IIter, _Funct) [with _IIter = __gnu_cxx::__normal_iterator<std::basic_string<char>*, std::vector<std::basic_string<char> > >; _Funct = bind_from_memory]’: 
/home/chap/private/WDI/git/Block.h:227:2: required from ‘void Block::populate_output_record(const D_RecordType&, Function) [with Function = bind_from_memory; D_RecordType = std::basic_string<char>]’ 
tom.cpp:901:8: required from here 
/usr/include/c++/4.7/bits/stl_algo.h:4442:2: error: no match for call to ‘(bind_from_memory) (std::basic_string<char>&)’ 
tom.cpp:864:8: note: candidate is: 
tom.cpp:871:10: note: void bind_from_memory::operator()(M_Field_Iter) 
tom.cpp:871:10: note: no known conversion for argument 1 from ‘std::basic_string<char>’ to ‘M_Field_Iter {aka __gnu_cxx::__normal_iterator<std::basic_string<char>*, std::vector<std::basic_string<char> > >}’ 
make: *** [tom.o] Error 1 

Я не могу найти его. Для меня, это говорит о том, что кто-то хочет пропускать string& к bind_from_memory::operator()(M_Field_Iter), и что, что «кто-то» может приходить в быть в результате:

Line 901: block.populate_output_record(rec_type, b); 

где Ь функтор. В «экземпляре» упоминается for_each. Ну, это, предположительно, запуск ИТЕРАТОРОВ у функтора, а не строка &. Я вижу NOWHERE, что я пытаюсь разыменовать итератор или напрямую отправлять строку в operator().

Я знаю, что не все декларации/определения показаны здесь, но, надеюсь, этого достаточно, чтобы кто-то мог заметить мою ошибку. Я уже ослеп. Весьма признателен.

tom.cpp

// ============================================================================ 
// 
// This is a functor that gets applied as we traverse the fieldname 
// vector. It uses fieldname to retrieve a value from memory, and 
// push_back()s the value onto the value vector. 
struct bind_from_memory { 
    // CTOR - bind object to MemoryBank and to MemRef_Vec 
    bind_from_memory(MemoryBank& memory, D_MemRef_Vec* memrefs_ptr) : 
    memory_map(memory), 
    memref_vec(*memrefs_ptr) {}; 

    // Overload of(), enabling calls to 
    // bind_from_memory(M_Field_Iter) 
    void operator()(M_Field_Iter field_iter) { // <<------Line 871---------------- 
    MemoryBank::iterator i; 
    if ((i = memory_map.find(*field_iter)) != memory_map.end()) { 
     memref_vec.emplace_back(i->second); 
    } 
    else { 
     memref_vec.emplace_back(); // not found, default "" 
    } 
    } 
private: 
    // bound for the duration of a single populate_output_record 
    MemoryBank& memory_map; // we retrieve values from here 
    D_MemRef_Vec& memref_vec; // we push_back the values onto this 
}; 

// ---------------------------------------------------------------------------- 
// bind_output_record(memory, block, record) 
// 
// Fill out an output record by pulling its field values from memory. 
// 
// Initialize a zero-length record vector, and then invoke populate_output_record 
// to traverse the fieldnames, invoking bind_from_memory on every iteration. 
// bind_from_memory(
// 
void 
bind_output_record(MemoryBank& memory, Block &block, const D_RecordType &rec_type) { 
    block.add_record(rec_type); // create record stub 
    bind_from_memory b(memory, 
       block.get_output_record_ptr(rec_type)); 
    block.populate_output_record(rec_type, 
       b); // <<--- Line 901 ---------------------------- 
} 

Block.cpp

M_Field_Range 
Block::make_field_range(const D_RecordType& record_type) { 

    // point to fieldname vector 
    M_Field_Vec& fields = m_record_hash->at(record_type).second; 

    return std::make_pair(fields.begin(), 
       fields.end() 
      ); 
} 

Block.h

// typedef pair<M_Field_Iter, M_Field_Iter> M_Field_Range; 

M_Field_Range   make_field_range(const D_RecordType&); 

template <typename Function> 
void 
populate_output_record(const D_RecordType& record_type, 
       Function func) { 
    M_Field_Range fields = make_field_range(record_type); 

    std::for_each(fields.first, fields.second, func); 
} 

ОБНОВЛЕНИЕ 1: M_Record_Hash и сотрудники, в соответствии с просьбой

typedef string       M_FieldName; 
typedef int        M_FieldPosition; 
typedef string       M_RecordType; 
typedef bool        M_RecordMandatory; 
typedef char        M_BlockFunction; 
typedef string       M_BlockType; 

typedef vector<M_FieldName>    M_Field_Vec; 
typedef boost::unordered_map<M_FieldName, M_FieldPosition> 
              M_FieldIndex_Hash; 
typedef pair<M_FieldIndex_Hash, M_Field_Vec> 
              M_FieldInfo_Pair; 

typedef boost::unordered_map<M_RecordType, M_FieldInfo_Pair> 
              M_Record_Hash; 
+1

вы всегда можете попробовать обычный цикл 'for'. они мне нравятся. нет непонятных ошибок. –

+0

@ Cheersandhth.-Alf: Это был действительно блестящий ответ, особенно учитывая то, что проблема оказывается. Это заставило мой код скомпилировать. Конечно, я проходил итераторы, и это то, что я как-то думал, что делал. – Chap

ответ

2

for_each не передает функторам итераторы, он передает функторы независимо от разыменования итераторов.

__gnu_cxx::__normal_iterator<std::basic_string<char>*, std::vector<std::basic_string<char> > > 

Указывает вы итерацию над vector<string>. Для этого ваш функтор должен принимать типы, совместимые с string (то есть string или string& или const string&), а не итераторы, которые он сейчас делает.

+0

Это похоже на факт. 'for_each' не передает свой итератор в функтор, это * dereferences * его итератор в первую очередь. Это правильный ответ. – Chap

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