signed/unsigned mismatch
От: igna Россия  
Дата: 19.08.08 09:26
Оценка:
Как без использования #pragma warning изменить нижеприведенный пример, чтобы избавиться от предупреждения?

#include <algorithm>
#include <list>
#include <vector>
using namespace std;

template <class CONT, class FI>
bool my_copy(CONT const& source, FI first, FI last)
{
    if (source.size() > last - first) // VC++ 9.0 - warning C4018: '>' : signed/unsigned mismatch
        return false;
    copy(source.begin(), source.end(), first);
    return true;
}

int main()
{
    list<int> l;
    vector<int> v;
    my_copy(l, v.begin(), v.end());
}
Re: signed/unsigned mismatch
От: php-coder Чехия http://slava-semushin.blogspot.com
Дата: 19.08.08 09:29
Оценка:
Здравствуйте, igna, Вы писали:

I>Как без использования #pragma warning изменить нижеприведенный пример, чтобы избавиться от предупреждения?


Попробуйте так:

template <class CONT, class FI>
bool my_copy(CONT const& source, FI first, FI last)
{
    if (source.size() > static_cast<size_t>(last - first))
        return false;
    copy(source.begin(), source.end(), first);
    return true;
}
Re: signed/unsigned mismatch
От: Анатолий Широков СССР  
Дата: 19.08.08 09:30
Оценка: 5 (2)
Здравствуйте, igna, Вы писали:

I>Как без использования #pragma warning изменить нижеприведенный пример, чтобы избавиться от предупреждения?


...
template <class CONT, class FI>
bool my_copy(CONT const& source, FI first, FI last)
{
    if (source.size() > std::distance(first, last)) // ok
        return false;
    copy(source.begin(), source.end(), first);
    return true;
}
...
Re[2]: signed/unsigned mismatch
От: igna Россия  
Дата: 19.08.08 09:40
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

АШ>    if (source.size() > std::distance(first, last)) // ok


Так нет же, предупреждение не исчезло никуда. Что впрочем не удивительно, поскольку distance возвращает difference_type, то есть тот же тип, что и у выражения last — first.
Re[3]: signed/unsigned mismatch
От: Анатолий Широков СССР  
Дата: 19.08.08 09:43
Оценка:
Здравствуйте, igna, Вы писали:

I>Здравствуйте, Анатолий Широков, Вы писали:


I>
АШ>>    if (source.size() > std::distance(first, last)) // ok
I>


I>Так нет же, предупреждение не исчезло никуда. Что впрочем не удивительно, поскольку distance возвращает difference_type, то есть тот же тип, что и у выражения last — first.


Сорри, поторопился. Тогда я предлагаю сделать ход конем:

template <class CONT, class FI>
bool my_copy(CONT const& source, FI first, FI last)
{
    if (std::distance(source.begin(), source.end()) > std::distance(first, last)) // ok?
        return false;
    copy(source.begin(), source.end(), first);
    return true;
}
Re[4]: signed/unsigned mismatch
От: igna Россия  
Дата: 19.08.08 09:49
Оценка: +1
Здравствуйте, Анатолий Широков, Вы писали:

АШ>    if (std::distance(source.begin(), source.end()) > std::distance(first, last)) // ok?


Да, но неэффективно в случае list.
Re: signed/unsigned mismatch
От: Bell Россия  
Дата: 19.08.08 09:52
Оценка: +1
Здравствуйте, igna, Вы писали:

Использование distance для определения размера диапазона безусловно верно, но исходной проблемы это не решает:

24.2
...
template <class InputIterator>
typename iterator_traits<InputIterator>::difference_type
distance(InputIterator first, InputIterator last);


difference_type — это знаковый тип (см. таблицу 65), а size_type — беззнаковый (та же таблица 65). Так что без явного каста даже и с std::difference предупреждение не побороть. Тем более что

size_type can represent any non-negative value of difference_type

Та же таблица 65.

В общем можно как-то вот так:
if (source.size() > (CONT::size_type)std::distance(first, last)) // ok
Любите книгу — источник знаний (с) М.Горький
Re: signed/unsigned mismatch
От: Were  
Дата: 19.08.08 09:57
Оценка:
Здравствуйте, igna, Вы писали:

I>Как без использования #pragma warning изменить нижеприведенный пример, чтобы избавиться от предупреждения?


Я бы сделал так:
if ( last < first || source.size() > static_cast< CONT::size_type >( last - first ))
    return false;
Re[2]: signed/unsigned mismatch
От: Bell Россия  
Дата: 19.08.08 10:01
Оценка:
Здравствуйте, Were, Вы писали:

W>Здравствуйте, igna, Вы писали:


I>>Как без использования #pragma warning изменить нижеприведенный пример, чтобы избавиться от предупреждения?


W>Я бы сделал так:

W>
W>if ( last < first || source.size() > static_cast< CONT::size_type >( last - first ))
W>    return false;
W>


Далеко не для всех типов итераторов определен operator <
Любите книгу — источник знаний (с) М.Горький
Re[3]: signed/unsigned mismatch
От: Were  
Дата: 19.08.08 10:08
Оценка:
Здравствуйте, Bell, Вы писали:

B>Здравствуйте, Were, Вы писали:


W>>Здравствуйте, igna, Вы писали:


I>>>Как без использования #pragma warning изменить нижеприведенный пример, чтобы избавиться от предупреждения?


W>>Я бы сделал так:

W>>
W>>if ( last < first || source.size() > static_cast< CONT::size_type >( last - first ))
W>>    return false;
W>>


B>Далеко не для всех типов итераторов определен operator <


operator -, кстати, тоже. И, скорее всего, это одни и те же итераторы )
Re: signed/unsigned mismatch
От: k55 Ниоткуда  
Дата: 19.08.08 10:16
Оценка:
А вот так?

  bool my_copy(CONT const& source, FI first, FI last)
  {
        FI _size = source.size();
    if (_size > last - first) // VC++ 9.0 - warning C4018: '>' : signed/unsigned mismatch
        return false;
    copy(source.begin(), source.end(), first);
    return true;
  }
Если есть желание — найдется 1000 возможностей.
Если нет желания — найдется 1000 причин.
Re[2]: signed/unsigned mismatch
От: igna Россия  
Дата: 19.08.08 10:16
Оценка:
Здравствуйте, Bell, Вы писали:

B>if (source.size() > (CONT::size_type)std::distance(first, last)) // ok


Всегда ли sizeof(FI::difference_type) будет не больше sizeof(CONT::size_type)? Ведь можно написать STL complient container size_type которого будет к примеру unsigned short.
Re: signed/unsigned mismatch
От: Кодт Россия  
Дата: 19.08.08 10:21
Оценка: +2
Здравствуйте, igna, Вы писали:

I>Как без использования #pragma warning изменить нижеприведенный пример, чтобы избавиться от предупреждения?


В данном случае можно положиться на то, что size() имеет тип size_t, а distance(first,last) — ptrdiff_t; это типы одинаковой разрядности.

Если положиться также на то, что размер контейнера не превосходит половину адресного пространства, то
if( static_cast<ptrdiff_t>(size) > delta )

Если положиться на то, что first<=last, то
if( size > static_cast<size_t>(delta) )

А писать какой-то обобщённый компаратор — больше затрат, чем смысла.
Перекуём баги на фичи!
Re[2]: signed/unsigned mismatch
От: igna Россия  
Дата: 19.08.08 10:21
Оценка:
Здравствуйте, k55, Вы писали:

k55>        FI _size = source.size();


Это ошибка.
Re[3]: signed/unsigned mismatch
От: Bell Россия  
Дата: 19.08.08 10:22
Оценка:
Здравствуйте, igna, Вы писали:

I>Здравствуйте, Bell, Вы писали:


I>
B>>if (source.size() > (CONT::size_type)std::distance(first, last)) // ok
I>


I>Всегда ли sizeof(FI::difference_type) будет не больше sizeof(CONT::size_type)? Ведь можно написать STL complient container size_type которого будет к примеру unsigned short.


Я же уже писал:

size_type can represent any non-negative value of difference_type

Этому требованию должны удовлетворять все стандартные контейнеры — смотри таблицу 65 в 23.1.
Любите книгу — источник знаний (с) М.Горький
Re[4]: signed/unsigned mismatch
От: igna Россия  
Дата: 19.08.08 10:32
Оценка:
Здравствуйте, Bell, Вы писали:

B>size_type can represent any non-negative value of difference_type


Это верно для случая, когда size_type и difference_type определены в одном и том же контейнерном типе.
Re[5]: signed/unsigned mismatch
От: Bell Россия  
Дата: 19.08.08 11:00
Оценка: 5 (2)
Здравствуйте, igna, Вы писали:

I>Здравствуйте, Bell, Вы писали:


I>

B>>size_type can represent any non-negative value of difference_type


I>Это верно для случая, когда size_type и difference_type определены в одном и том же контейнерном типе.

Формалист

Ну вот тогда обходной маневр:
if ((typename CONT::difference_type)source.size() > distance(first, last)) // ok
Любите книгу — источник знаний (с) М.Горький
Re[2]: signed/unsigned mismatch
От: Юрий Жмеренецкий ICQ 380412032
Дата: 19.08.08 11:24
Оценка: 2 (1)
Здравствуйте, Bell, Вы писали:

...
B>difference_type — это знаковый тип (см. таблицу 65), а size_type — беззнаковый (та же таблица 65). Так что без явного каста даже и с std::difference предупреждение не побороть. Тем более что
B>

B>size_type can represent any non-negative value of difference_type

B>Та же таблица 65.

B>В общем можно как-то вот так:

B>
B>if (source.size() > (CONT::size_type)std::distance(first, last)) // ok
B>


Явный каст можно "спрятать":
if(source.size() > std::distance(last, first) + 0u)
Re[3]: signed/unsigned mismatch
От: Bell Россия  
Дата: 19.08.08 11:32
Оценка: +3
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>Явный каст можно "спрятать":

ЮЖ>
ЮЖ>if(source.size() > std::distance(last, first) + 0u)
ЮЖ>


ИМХО лучше не маскировать своих намерений.
Любите книгу — источник знаний (с) М.Горький
Re[2]: signed/unsigned mismatch
От: igna Россия  
Дата: 20.08.08 06:15
Оценка:
Здравствуйте, php-coder, Вы писали:

PC>    if (source.size() > static_cast<size_t>(last - first))


size_t не обязан быть самым большим из целочисленных типов, то есть результат вычисления last — first может не поместиться в size_t.
Re[3]: signed/unsigned mismatch
От: Кодёнок  
Дата: 20.08.08 07:03
Оценка:
Здравствуйте, igna, Вы писали:

I>size_t не обязан быть самым большим из целочисленных типов, то есть результат вычисления last — first может не поместиться в size_t.


Расскажи какому математику, что у программистов проблема со сравнением чисел из одного подмножеста Z с абсолютно однозначно определенным порядком, что они в спецификации лазят и спорят — тот и помереть со смеху может
Re[3]: signed/unsigned mismatch
От: FlamingWind Россия  
Дата: 20.08.08 07:35
Оценка:
Здравствуйте, igna, Вы писали:

I>Здравствуйте, php-coder, Вы писали:


I>
PC>>    if (source.size() > static_cast<size_t>(last - first))
I>


I>size_t не обязан быть самым большим из целочисленных типов, то есть результат вычисления last — first может не поместиться в size_t.


Насколько я понимаю, неявное привидение типа здесь все равно будет. Поэтому, собственно говоря, и выдается варнинг...
Вопрос к более сведующим, в сравнении (last — first) будет всегда приводиться к size_t?
Re[4]: signed/unsigned mismatch
От: igna Россия  
Дата: 20.08.08 09:16
Оценка:
Здравствуйте, Кодёнок, Вы писали:

Кё>Расскажи какому математику, что у программистов проблема со сравнением чисел из одного подмножеста Z с абсолютно однозначно определенным порядком, что они в спецификации лазят и спорят — тот и помереть со смеху может


Вот еще пример для математиков:

#include <iostream>
using namespace std;

int main()
{
    unsigned int one = 1;
    if (one < -1)
        cout << "1 < -1\n";
}


Логика создателей C разрешивших неявное преобразование int в unsigned int мне непонятна. Эффективность и в случае необходимости явного преобразования типа никуда бы не делась.
Re[2]: signed/unsigned mismatch
От: igna Россия  
Дата: 20.08.08 09:21
Оценка:
Здравствуйте, Кодт, Вы писали:

К>if( size > static_cast<size_t>(delta) )


size_t не обязан быть самым большим из целочисленных типов, то есть delta может не поместиться в size_t.
Re: signed/unsigned mismatch
От: wils0n www.atzone.org
Дата: 20.08.08 11:52
Оценка: 2 (1)
Здравствуйте, igna, Вы писали:

I>template <class CONT, class FI>

I>bool my_copy(CONT const& source, FI first, FI last)
I>{
I> if (source.size() > last — first) // VC++ 9.0 — warning C4018: '>' : signed/unsigned mismatch
I> return false;
I> copy(source.begin(), source.end(), first);
I> return true;
I>}
[/ccode]

на сколько я понимаю, по логике программы всё корректно, напрягает только варнинг, возникший из-за оператора вычитания. А если его заменить на сложение?
if (source.size() + first > last) // так нормально?
    return false;
gcc 4.2
Re[2]: signed/unsigned mismatch
От: igna Россия  
Дата: 20.08.08 12:28
Оценка:
Здравствуйте, wils0n, Вы писали:

W>if (source.size() + first > last) // так нормально?


Интересно, но не работает, если sizeof(source.size()) > sizeof(first). Ситуация не самая вероятная, но все же возможная.
Re[2]: signed/unsigned mismatch
От: igna Россия  
Дата: 20.08.08 12:32
Оценка:
Здравствуйте, Were, Вы писали:

W>if ( last < first || source.size() > static_cast< CONT::size_type >( last - first ))


Здесь возможно отсечение старших битов результата вычисления выражения last — first, если sizeof(CONT::size_type) < sizeof(last — first).
Re[4]: signed/unsigned mismatch
От: Кодт Россия  
Дата: 20.08.08 13:10
Оценка:
Здравствуйте, Bell, Вы писали:

B>size_type can represent any non-negative value of difference_type


...Из чего не следует, что он может представлять что-то сверх того.
Этим лагом в стандарте пользуются разработчики компиляторов, делая size_t беззнаковым той же разрядности, что и ptrdiff_t.
В общем, удобно. Не считая проблем со смешанной арифметикой.


Вот если бы наоборот, утверждалось бы, что difference_type мог представлять любое реалистичное значение size_type, то можно было бы спокойно кастить size() к difference_type и не париться.
По смыслу — так оно и есть.

Если компилятор честный и допускает существование контейнеров размером более чем в половину сегмента данных, то ptrdiff_t должен быть длиннее, чем адресные регистры — чтоб хранить знак разности.
Но тогда, для удобства, нужно поднять и разрядность size_t.
И получить мучительную арифметику, не влезающую в регистры процессора.
Перекуём баги на фичи!
Re[3]: signed/unsigned mismatch
От: Кодт Россия  
Дата: 20.08.08 13:10
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>Явный каст можно "спрятать":

ЮЖ>if(source.size() > std::distance(last, first) + 0u)


Какой бы каст ни был — явный, неявный, — здесь чисто математически нужны внешние гарантии, что last<=first. (именно так! нужно быть внимательным к тому, что пишешь). В противном случае отрицательное значение превратится в мега-положительное.
Перекуём баги на фичи!
Re[4]: signed/unsigned mismatch
От: Кодт Россия  
Дата: 20.08.08 13:14
Оценка: +1
Здравствуйте, Кодёнок, Вы писали:

Кё>Расскажи какому математику, что у программистов проблема со сравнением чисел из одного подмножеста Z с абсолютно однозначно определенным порядком, что они в спецификации лазят и спорят — тот и помереть со смеху может


Расскажи этому математику, что это только кажется, что подмножество одно и то же, а на самом деле там два кольца вычетов, по-разному отображаемые на Z и обратно.
Он не со смеху помрёт, а с печали за наши судьбы.
Перекуём баги на фичи!
Re[3]: signed/unsigned mismatch
От: Кодт Россия  
Дата: 20.08.08 13:26
Оценка:
Здравствуйте, igna, Вы писали:

I>
К>>if( size > static_cast<size_t>(delta) )
I>


I>size_t не обязан быть самым большим из целочисленных типов, то есть delta может не поместиться в size_t.


Что это за контейнер, в котором неотрицательная* дельта вылезает из размера?
Противоречие здравому смыслу, однако.

*) про неотрицательность я особо оговорился строчкой выше (не вошло в твою цитату)
Перекуём баги на фичи!
Re[3]: signed/unsigned mismatch
От: Кодт Россия  
Дата: 20.08.08 13:39
Оценка: 2 (1) +1
Здравствуйте, igna, Вы писали:

I>
W>>if (source.size() + first > last) // так нормально?
I>


I>Интересно, но не работает, если sizeof(source.size()) > sizeof(first). Ситуация не самая вероятная, но все же возможная.


Не работает по другой причине: first+source.size() может вылететь за пределы области определения этих итераторов. В этом случае поведение не определено, или, в лучшем случае, не специфицировано.
В исходном примере копировали вектор со списком. Сделайте advance(first,source.size()) за конец списка, узнаете всякое нехорошее.
Перекуём баги на фичи!
Re[4]: signed/unsigned mismatch
От: Кодт Россия  
Дата: 20.08.08 13:41
Оценка:
К>Что это за контейнер, в котором неотрицательная* дельта вылезает из размера?
К>Противоречие здравому смыслу, однако.

Впрочем, если последовательность (first,last) отображает что-то за пределами адресного пространства (мега-файл; функцию над длинными целыми; ещё что-то тому подобное), то конечно.
Перекуём баги на фичи!
Re: signed/unsigned mismatch
От: Кодт Россия  
Дата: 20.08.08 13:57
Оценка: 2 (1) +1
Здравствуйте, igna, Вы писали:

<>

А нужно ли иметь такую функцию, которая в случае перебора длины просто выходит с false?
Может быть, лучше копировать сколько возможно, и возвращать остаток обоих последовательностей?

template<class I, class O>
pair<I,O> copy_zipped(I ib, I ie, O ob, O oe)
{
  for( ; ib!=ie && ob!=oe; ++ib, ++ob )
    *ob = *ib;
  return make_pair(ib,ob);
}


// заполнение контейнера из множества источников
destination::iterator top = dst.begin(), enough = dst.end();
if(top != enough)
  top = copy_zipped(src1.begin(), src1.end(), top, enough).second;
if(top != enough)
  top = copy_zipped(src2.begin(), src2.end(), top, enough).second;
.....

// распихивание контейнера во множество приёмников
source::iterator start = src.begin(), finish = dst.end();
if(start != finish)
  start = copy_zipped(start, finish, dst1.begin(), dst1.end()).first;
if(start != finish)
  start = copy_zipped(start, finish, dst2.begin(), dst2.end()).first;
.....
Перекуём баги на фичи!
Re[5]: signed/unsigned mismatch
От: Кодёнок  
Дата: 21.08.08 09:11
Оценка:
Здравствуйте, Кодт, Вы писали:

Кё>>Расскажи какому математику, что у программистов проблема со сравнением чисел из одного подмножеста Z с абсолютно однозначно определенным порядком, что они в спецификации лазят и спорят — тот и помереть со смеху может


К>Расскажи этому математику, что это только кажется, что подмножество одно и то же, а на самом деле там два кольца вычетов, по-разному отображаемые на Z и обратно.


Какие еще кольца вычетов?!

Есть какие-то теоретические трудности со сравнением двух чисел из произвольных интервалов A..B и C..D? Или то, что они закодированы в виде 0..(B-A) и 0..(D-C) принципиально усложняет задачу?
Re[6]: signed/unsigned mismatch
От: Кодт Россия  
Дата: 21.08.08 12:24
Оценка: +1
Здравствуйте, Кодёнок, Вы писали:

Кё>Какие еще кольца вычетов?!


Беззнаковые целые реализуют арифметику по модулю 2^разрядность.

Кё>Есть какие-то теоретические трудности со сравнением двух чисел из произвольных интервалов A..B и C..D? Или то, что они закодированы в виде 0..(B-A) и 0..(D-C) принципиально усложняет задачу?


Трудности в том, что в С++ нет "произвольных интервалов". Есть независимые множества аппаратно реализованных типов, между которыми установлены отображения. Это постоянно ускользает из внимания, за кажущейся похожестью этих типов на подмножества Z и R.

Задачу усложняет то, что операция сравнения работает быстро, только если числа относятся к одному и тому же множеству. Не к абстрактному Z или R, а к аппаратно реализованному.
А когда множества разные, то есть 3 пути
— или дорогое сравнение гетерогенных объектов (мысленно отображая их на Z или R)
— или дешёвое приведение к какому-то аппаратно реализованному типу и затем дешёвое сравнение
— или послать всех нафиг
Как в спецификации сказано, так и будет сделано.

В Хаскелле ты не сможешь сравнить Int (аппаратный) и Integer (неограниченная разрядность) без предварительного отображения одного на другое. То есть, это 3-й вариант.
В Питоне — им терять нечего — язык интерпретируемый, расширяют до длинного целого и сравнивают.
В С++ — ради скорости говорят, что программист ССЗБ. Если дефолтное приведение типов устраивает, то нет переплаты. Если не устраивает — то нужно явно переплатить именно в этом месте.
Перекуём баги на фичи!
Re[7]: signed/unsigned mismatch
От: igna Россия  
Дата: 21.08.08 14:43
Оценка:
Здравствуйте, Кодт, Вы писали:

К>В С++ — ради скорости говорят, что программист ССЗБ.


Никакой скорости не повредило бы, если бы при сравнении (сложении, вычитании ...) int и unsigned int требовалось явное приведение типа. Даже скорости написания программы с учетом отладки пошло бы на пользу.
Re[4]: signed/unsigned mismatch
От: Sergey Chadov Россия  
Дата: 21.08.08 17:50
Оценка:
Здравствуйте, Кодт, Вы писали:


К>Что это за контейнер, в котором неотрицательная* дельта вылезает из размера?


B-дерево
--
Sergey Chadov

... << RSDN@Home 1.2.0 alpha rev. 685>>
Re: signed/unsigned mismatch
От: IROV..  
Дата: 21.08.08 20:10
Оценка:
Здравствуйте, igna, Вы писали:

if ( first > last - source.size()) //ok

я не волшебник, я только учусь!
Re[2]: signed/unsigned mismatch
От: igna Россия  
Дата: 22.08.08 07:20
Оценка:
Здравствуйте, IROV.., Вы писали:

IRO>if ( first > last - source.size()) //ok


Было и не прошло: здесь
Автор: Кодт
Дата: 20.08.08
.
Re[5]: signed/unsigned mismatch
От: Кодт Россия  
Дата: 22.08.08 11:30
Оценка:
Здравствуйте, Sergey Chadov, Вы писали:

К>>Что это за контейнер, в котором неотрицательная* дельта вылезает из размера?


SC>B-дерево


Если имеется в виду фасад к внешнему файлу — то без разницы, б-деревянный он или плоский.
Но это неинтересно.

А если дерево в памяти — то либо дельта итераторов считается некорректно (с дырками в страницах), либо она из размера не может вылезти.
Перекуём баги на фичи!
Re[6]: signed/unsigned mismatch
От: igna Россия  
Дата: 22.08.08 12:26
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Если имеется в виду фасад к внешнему файлу — то без разницы, б-деревянный он или плоский.

К>Но это неинтересно.

В смысле неинтересно? Предлагаемое решение
Автор: Кодт
Дата: 19.08.08
в этом случае некорректно.
Re[3]: signed/unsigned mismatch
От: IROV..  
Дата: 22.08.08 13:36
Оценка:
Здравствуйте, igna, Вы писали:

I>Здравствуйте, IROV.., Вы писали:


I>
IRO>>if ( first > last - source.size()) //ok
I>


I>Было и не прошло: здесь
Автор: Кодт
Дата: 20.08.08
.

Ну и где здесь сложение?

почему не прошло?
я не волшебник, я только учусь!
Re[4]: signed/unsigned mismatch
От: igna Россия  
Дата: 22.08.08 13:55
Оценка:
Здравствуйте, IROV.., Вы писали:

IRO>почему не прошло?


Почти цитата: "last-source.size() может вылететь за пределы области определения этих итераторов"
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.