У меня есть приложение Visual Studo 2008 C ++, в котором я пытаюсь добавить поддержку итераторов в устаревшую структуру связанного списка C-API.Интерфейс C выглядит следующим образом:
typedef struct _LINKED_LIST_INFO {
struct _LINKED_LIST_INFO* Next;
const char* name;
// more elements. some are fixed-size; others are pointers to other structures.
} LINKED_LIST_INFO;
DWORD GetLinkedList( LINKED_LIST_INFO* pInfo, PULONG pOutBufLen );
Я бы хотел использовать его следующим образом:
int _tmain( int /*argc*/, _TCHAR* /*argv*/[] )
{
MyLinkedList elements;
for( MyLinkedList::const_iterator it = elements.begin();
it != elements.end();
++it )
{
printf( "Name: %s\r\n", it->Name().c_str() );
}
return 0;
}
Итак, я создал эти 3 класса.Но у моего класса MyInfoIterator
есть проблема с operator->()
.Я не могу вернуть временный указатель на MyInfo
, поэтому я получаю сообщение об ошибке: error C2440: 'return' : cannot convert from 'MyInfo' to 'const MyInfo *'
Что является хорошим решением этой проблемы?
/// wrap the legacy C structure and provide C++ accessors
class MyInfo
{
public:
MyInfo( const LINKED_LIST_INFO& info ) : elem_( info ) { };
std::string Name() const { return elem_.name; };
private:
/// one element of the linked list
const LINKED_LIST_INFO& elem_;
}; // class MyInfo
namespace detail {
/// buffer to hold the legacy C linked-list
typedef std::vector< BYTE > MyBuffer;
/// iterator support for the legacy C linked-list
class MyInfoIterator
: public std::iterator< std::input_iterator_tag, MyInfo >
{
public:
explicit MyInfoIterator( MyBuffer& list ) : data_( list )
{
elem_ = reinterpret_cast< LINKED_LIST_INFO* >( &data_.front() );
};
MyInfoIterator() : elem_( NULL ) { };
MyInfoIterator& operator++()
{
elem_ = elem_->Next;
return *this;
};
value_type operator*() { return *elem_; };
// error C2440: 'return' : cannot convert from 'MyInfo' to 'const MyInfo *'
const value_type* operator->() { return elem_; };
friend bool operator==( const MyInfoIterator& i,
const MyInfoIterator& j )
{
return i.elem_ == j.elem_;
};
private:
/// linked-list of elements
MyBuffer data_;
/// current position within the element list
LINKED_LIST_INFO* elem_;
}; // class MyInfoIterator
bool operator!=( const MyInfoIterator& i, const MyInfoIterator& j )
{
return !operator==( i, j );
}
}; // namespace detail
/// provide iterator access for the legacy C linked-list API
class MyLinkedList
{
public:
typedef detail::MyInfoIterator const_iterator;
const_iterator begin() const
{
ULONG size = sizeof( LINKED_LIST_INFO );
detail::MyBuffer buffer( size );
DWORD ec = ::GetLinkedList(
reinterpret_cast< LINKED_LIST_INFO* >( &buffer.front() ), &size );
if( ERROR_BUFFER_OVERFLOW == ec )
{
buffer.resize( size );
ec = ::GetLinkedList(
reinterpret_cast< LINKED_LIST_INFO* >( &buffer.front() ), &size );
}
if( ERROR_SUCCESS != ec )
Win32Exception::Throw( ec );
return const_iterator( buffer );
};
const_iterator end() const { return const_iterator(); };
}; // class MyInfo
Спасибо, PaulH
Редактировать:
Я не могу изменить устаревший API или связанную с ним структуру.
Edit2:
Я думаю, что у меня есть рабочее решение, которое сохраняет мое намерение скрыть базовую реализацию связанного списка и поддерживает разделение обязанностей для каждого класса, возвращая адрес static MyInfo
.
class MyInfo
{
// ...
protected:
MyInfo() : info_( NULL ) { };
void Set( const LINKED_LIST_INFO* info ) { info_ = info; };
private:
friend MyInfoIterator;
const LINKED_LIST_INFO* info_;
};
const value_type& MyInfoIterator::operator*() const
{
static MyInfo info;
info.Set( elem_ );
return info;
};
const value_type* MyInfoIterator::operator->() const
{
static MyInfo info;
info.Set( elem_ );
return &info;
};