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.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.