Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Visual C++/MFC/WTL > [MSVC 2008] преобразовать указатель к итератору


Автор: borisbn 5.3.2011, 12:33
Добрый день!
В 2008-й студии на такой код
Код

typedef std::vector< int > IVector;
const int * p;
IVector::const_iterator it( p );

выдаёт ошибку
Цитата

error C2664: 'std::_Vector_const_iterator<_Ty,_Alloc>::_Vector_const_iterator(const std::_Vector_const_iterator<_Ty,_Alloc> &)' : cannot convert parameter 1 from 'const int *' to 'const std::_Vector_const_iterator<_Ty,_Alloc> &' 

погуглил, поMSDNил нашёл 2 дефайна, которые, как мне казалось, отвечают за это.
добавил в проект два дефайна
Цитата

_SCL_SECURE_NO_WARNINGS
и
_HAS_ITERATOR_DEBUGGING 0

результат тот же.
Подскажите, пожалуйста, как в студии преобразовать указатель к итератору.
Спасибо.

P.S. без const тоже пробовал. результат тот же

Автор: maxim1000 5.3.2011, 14:51
хм... а с чего бы это им кастоваться друг к другу
итератор является указателем разве что семантически, да и то уже перерос это понятие
в терминах языка итератор и указатель - две разные вещи

используя специфику std::vector (то, что он обязан хранить объекты друг за другом) можно сделать так:
Код

std::vector<int>::iterator i=someVector.begin()+(p-&someVector.front());


Добавлено через 2 минуты и 11 секунд
P.S.
есть сильное ощущение, что стоит обратить внимание на ту функциональность, которая генерирует эти указатели - может она должна выдавать итераторы?

Автор: alexvs11 5.3.2011, 14:55
ни разу не обязано работать такое преобразование
iterator сам себе объект, кастование к нему не имеет здравого смысла, ибо итератор должен скрывать в себе реализацию контейнера и самого обхода, а не открывать к ним лазейки

и в чем смысл использования?

Автор: borisbn 6.3.2011, 12:19
сорри, что не отвечал вовремя - женщин поздравляли smile
Цитата(maxim1000 @  5.3.2011,  14:51 Найти цитируемый пост)
а с чего бы это им кастоваться друг к другу

а почему бы и нет ?
Код

std::что_нибудь_требующее_итератор( pointer_to_int, pointer_to_int + length )

так что-ли тоже нельзя ?

Цитата(maxim1000 @  5.3.2011,  14:51 Найти цитируемый пост)
есть сильное ощущение, что стоит обратить внимание на ту функциональность, которая генерирует эти указатели - может она должна выдавать итераторы?

на 250% согласен, но код не мой, там такого немало, и на дебилдере он компилируется, а на студии - нет (кстати, на liveworkspace пробовал - работает, а там, кажется gcc)
на самом деле я упростил код до минимума. в оригинале было так
Код

bool findSequence( const unsigned char * buf, unsigned int buf_len, const UCVector & seq, unsigned int & pos ) {
    UCVector::const_iterator it = std::search( buf, // вот тут и ругался
       buf + buf_len, // здесь ессно тоже
       seq.begin(), seq.end() );
...
}


Автор: Albor 6.3.2011, 19:08
borisbn, возвращаемое значение алгоритма search  должно быть такого же типа как и тип итераторов диапазона для поиска, то есть const unsigned char *, почему в коде значение принимает другой тип не понятно - не выполняются требования к типам для данного алгоритма.

Автор: maxim1000 6.3.2011, 20:23
Цитата(borisbn @  6.3.2011,  12:19 Найти цитируемый пост)
а почему бы и нет ?
Код

std::что_нибудь_требующее_итератор( pointer_to_int, pointer_to_int + length )

так что-ли тоже нельзя ?

в такую сторону можно, т.к. итератор в C++ обобщает понятие указателя

более того, указатель - наиболее естественный итератор для "куска памяти", так что если передаётся unsigned char *buf, то и итератор в этом "куске памяти" должен быть указателем, как предложил Albor

а то ведь к коде функции вообще нет никаких оснований ожидать, что buf указывает на какой-либо контейнер, так что и приводить указатель на его элемент к итератору, специфическому для какого-то контейнера, неправильно...

Добавлено @ 20:28
кстати, а как потом используется it?
а то создаётся впечатление, что произошла обычная человеческая ошибка во время разработки этого кода, которую компилятор не отловил, - вместо типа первой пары итераторов для результата был выбран тип второй

Автор: borisbn 7.3.2011, 09:04
Цитата(maxim1000 @  6.3.2011,  20:23 Найти цитируемый пост)
а то ведь к коде функции вообще нет никаких оснований ожидать, что buf указывает на какой-либо контейнер, так что и приводить указатель на его элемент к итератору, специфическому для какого-то контейнера, неправильно...

неправильно то неправильно... чисто по человеческой логике, но мне непонятно, почему это не работает по "компиляторной" логике ? Почему не вызывается конструктор итератора типа iterator( T* ) ? Я посмотрел в коде студийного STL - там есть такой конструктор, он explicit, но, даже если я сделаю явное преобразование (как в самом первом посте), всё равно ошибка.

И, кстати, там этот конструктор "открывается", т.е. вообще присутствует в классе, по куче define'ов, так, что я так понимаю мне чтобы добиться компиляции этого кода, нужно просто прописать какой-то define в студии...

И ещё. Я не случайно выбрал именно этот раздел форума, т.к. этот код, повторюсь, работает и в билдере и в gcc.

То, что код не совсем корректный - ну может быть... убедили smile Но оооочень не хочется его переделывать, т.к. там такого много.

Автор: Earnest 9.3.2011, 12:30
explicit относится к конструктору, а не к преобразованию; это разные вещи вообще-то. Просто привыкаешь, что оно все работает само собой без дополнительных букв. Как раз поэтому и ругается, насколько я понимаю, что даже явное преобразование требует конструктора, который explicit, т.е. имеет право вызываться только лично программером. Используй форму конструктора, а не преобразования, тогда должно пройти. Я сталкивалась с тем, что в 2008 это дело строже, чем раньше было... Что, в общем, неплохо, ибо явное указание на грязь в коде...но при переходе между компиляторами, конечно, раздражает (типа все там работало, а здесь...). Что в билдере компилируется, не аргумент, реализация библиотеки другая. В 2003 тоже должно скомпилироваться. Лучше этого избегать. Тебе ведь правильно разъяснили, что указатель есть итератор, но обратное неверно.
С переделками действительно нужно поаккуратнее - практика показывает, что даже самые казалось бы безобидные изменения кода могут приводить к ошибкам, т.е. все требует тщательного тестирования... Попробуй обойтись малой кровью (используй для приведения форму конструктора), если уверен в сути.

Автор: borisbn 9.3.2011, 13:51
Цитата(Earnest @  9.3.2011,  12:30 Найти цитируемый пост)
Используй форму конструктора, а не преобразования, тогда должно пройти

дык, пробовал (см. самое первое сообщения этой темы)...
Цитата(Earnest @  9.3.2011,  12:30 Найти цитируемый пост)
Лучше этого избегать.

повторю, код не мой и его (кода) много. А если это на будущее - то спасибо, буду избегать.
Цитата(Earnest @  9.3.2011,  12:30 Найти цитируемый пост)
Что в билдере компилируется, не аргумент

ессно, не аргумент, но ведь и в gcc компилируется...
и ещё http://cplusplus.com/reference/std/iterator/iterator/ (пример в конце)

В общем, у меня вопрос не по корректности этого кода, а как заставить студию его откомпилировать (какой дефайн где прописать) ? Ответ - никак - тоже принимается, но с пруф-линком smile Спасибо.

Автор: Earnest 10.3.2011, 09:47
Цитата(borisbn @  9.3.2011,  14:51 Найти цитируемый пост)
дык, пробовал (см. самое первое сообщения этой темы)...

Пардон, пропустила...
Странно, точно помню, что у меня была такая же проблема при переходе с 2003 на 2008, использовались неявное преобразование, помог конструктор... правда вроде не const там было. 
Посмотрела еще раз проблемный код, который не компилируется:
Код

bool findSequence( const unsigned char * buf, unsigned int buf_len, const UCVector & seq, unsigned int & pos ) {
    UCVector::const_iterator it = std::search( buf, // вот тут и ругался
       buf + buf_len, // здесь ессно тоже
       seq.begin(), seq.end() );

Здесь результат ведь должен иметь тип первого итератора, т.е. константный указатель внутрь буфера (const unsigned char * buf). Раньше компилировалось, т.к. неявно преобразовывалось в UCVector::const_iterator. Но вообще-то это некорректно.

Добавлено через 2 минуты и 7 секунд
Вижу, об этом уже говорил Albor

Автор: borisbn 10.3.2011, 11:21
Цитата(Earnest @  10.3.2011,  09:47 Найти цитируемый пост)
Но вообще-то это некорректно.


Цитата(borisbn @  9.3.2011,  13:51 Найти цитируемый пост)
В общем, у меня вопрос не по корректности этого кода, а как заставить студию его откомпилировать (какой дефайн где прописать) ? Ответ - никак - тоже принимается, но с пруф-линком  Спасибо.

 smile 

Автор: Earnest 10.3.2011, 13:05
Те дефайны, которые ты привел, действительно позволяют конструировать итератор вектора из указателя, но не const указателя (точнее, не указателя на константу). Потому и не компилируется, несмотря на наличие явного конструктора. Там ведь так:
Код

typedef typename _Alloc::pointer _Tptr;
explicit _Vector_const_iterator(_Tptr _Ptr)

Кроме того, из приведенного кода непонятно, что такое UCVector. Если там хранятся unsigned char как в буфере, то скорее всего поможет отбитие const

Автор: borisbn 10.3.2011, 13:39
Цитата(Earnest @  10.3.2011,  13:05 Найти цитируемый пост)
то скорее всего поможет отбитие const

нет. 
Цитата(borisbn @  5.3.2011,  12:33 Найти цитируемый пост)
P.S. без const тоже пробовал. результат тот же

Код

typedef std::vector< int > IVector;
    int * p;
    IVector v;
    int * pp = std::search( p, p + 1, v.begin(), v.end() );
    IVector::iterator it( pp ); // Ошибка


Добавлено через 7 минут и 25 секунд
Ладно, забейте. Я уже вышел из ситуации ( м.б. не лучшим способом, но никто ж, пока, не подсказал лучший smile )
Я собрал на билдере из этого кода dll-ку, которую подключил к проекту на студии. Всё работает как надо.
Тему закрываю, но если возникнут идеи - you're wellcome smile

Автор: volatile 11.3.2011, 00:22
Цитата(borisbn @  10.3.2011,  11:21 Найти цитируемый пост)
как заставить студию его откомпилировать (какой дефайн где прописать) ? 

Сегодня решил немного покопаться в исходниках студийной стл.
В общем решение лежало близко...

Код

#define _SECURE_SCL 0
#define _HAS_ITERATOR_DEBUGGING 0
#include <vector>
#include <algorithm>

void aaa(int * p)
{
    typedef std::vector< int > IVector;
    IVector v;
    int * pp = std::search( p, p + 1, v.begin(), v.end() );
    IVector::iterator it(pp);        // Не константный работает
    IVector::const_iterator itc(pp); // И константный тоже!
}


Код

1>Compiling...
1>vingrad.cpp
1>Linking...
1>vingrad - 0 error(s), 0 warning(s)
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

MSVS 2008 И в дебаге, и в релизе.
smile

Автор: borisbn 11.3.2011, 09:23
volatile, спасибо огромное !!!
А ведь искал же... и даже видел эти дефайны... просто не дошло, что их нужно оба установить в 0.

P.S. К сожалению мой реальный (не тестовый) код всё равно без переделок не откомпиляешь, т.к. конструктор итератора explicit, а у меня
Код

UCVector::const_iterator it = std::search( buf, buf + buf_len, seq.begin(), seq.end() );


Но всё равно спасибо.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)