Как выяснить, что присваивать в итератор?
От: _Winnie Россия C++.freerun
Дата: 30.09.05 21:55
Оценка:
Имеется такой код:

template <class UnsignedInt, class OutIter>
OutIter print_unsinged(OutIter output, UnsignedInt in_int)
{
    typedef typename std::iterator_traits<OutIter>::value_type char_t;
    char_t tmp_chars[64];
    int n = 0;
    STATIC_ASSERT( UnsignedInt()-1 > 0, should_be_unsigned );

    while (in_int)
    {
        //idiv... gcc/icc optimize it away, msvc does not.
        tmp_chars[n++] = (char_t)('0' + in_int%10);
        in_int = in_int/10;
    }

    while(n--)
        *output++ = tmp_chars[n];

    return output;
}


Когда использую его как

    char buf[20];
    *print_unsinged(buf, 0xFFFFFFFF) = '\0';
    std::cout << buf;


то все в порядке, std::iterator_traits<OutIter>::value_type получается char.

но когда я использую его так
    std::vector<char> str;
    print_unsinged(std::back_inserter(str), 0xFFFFFFFF);


или так —

print_unsinged(std::ostream_iterator<char>(std::cout), 123U);


то возникает ошибка компиляции —
typename std::iterator_traits<OutIter>::value_type представляет собой void, и естесвенно ничего не работает.

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

и желательно, что бы на всех компиляторах без варнингов
если сделать просто typedef int char_t;
то получится —

test4.cpp(72) : warning C4244: 'argument' : conversion from 'char_t' to 'const char', possible loss of data
        test4.cpp(99) : see reference to function template instantiation 'OutIter print_unsinged<unsigned int,std::ostream_iterator<_Ty>>(OutIter,UnsignedInt)' being compiled
        with
        [
            OutIter=std::ostream_iterator<char>,
            _Ty=char,
            UnsignedInt=unsigned int
        ]
Правильно работающая программа — просто частный случай Undefined Behavior
Re: Как выяснить, что присваивать в итератор?
От: Aznog Россия  
Дата: 30.09.05 22:59
Оценка:
Здравствуйте, _Winnie, Вы писали:

_W>Имеется такой код:

_W>...

Вот простой способ, однако для всех итераторов с "плохим" value_type придется добавлять частичную специализацию it_traits:
template <class Iter>
struct it_traits
{
    typedef typename std::iterator_traits<Iter>::value_type;
};

template <class Container>
struct it_traits<std::back_insert_iterator<Container> >
{
    typedef typename Container::value_type value_type;
};

template <class CharType>
struct it_traits<std::ostream_iterator<CharType> >
{
    typedef typename std::ostream_iterator<CharType>::char_type value_type;
};

template <class UnsignedInt, class OutIter>
OutIter print_unsinged(OutIter output, UnsignedInt in_int)
{
    typedef typename it_traits<OutIter>::value_type char_t;
    char_t tmp_chars[64];
    int n = 0;
    STATIC_ASSERT( UnsignedInt()-1 > 0, should_be_unsigned );

    while (in_int)
    {
        //idiv... gcc/icc optimize it away, msvc does not.
        tmp_chars[n++] = (char_t)('0' + in_int%10);
        in_int = in_int/10;
    }

    while(n--)
        *output++ = tmp_chars[n];

    return output;
}

int main(int argc, _TCHAR* argv[])
{
    std::vector<char> vec;
    print_unsinged(std::back_inserter(vec), 0xFFFF);
    std::copy(vec.begin(), vec.end(), std::ostream_iterator<char>(std::cout));
    std::cout << std::endl;
    print_unsinged(std::ostream_iterator<char>(std::cout), 0xFFFFF);
    return 0;
}
Re: Как выяснить, что присваивать в итератор?
От: MaximE Великобритания  
Дата: 03.10.05 08:39
Оценка:
_Winnie wrote:

> Имеется такой код:

>
>
> template <class UnsignedInt, class OutIter>
> OutIter print_unsinged(OutIter output, UnsignedInt in_int)
> {
>     typedef typename std::iterator_traits<OutIter>::value_type char_t;
>     char_t tmp_chars[64];
>     int n = 0;
>     STATIC_ASSERT( UnsignedInt()-1 > 0, should_be_unsigned );
>
>     while (in_int)
>     {
>         //idiv... gcc/icc optimize it away, msvc does not.
>         tmp_chars[n++] = (char_t)('0' + in_int%10);
>         in_int = in_int/10;
>     }
>
>     while(n--)
>         *output++ = tmp_chars[n];
>
>     return output;
> }
>


Предлагаю в качестве буфера всегда использовать char. Здесь ты используешь только ASCII символы 0-9, которые во многих кодировках (и во всех юникодах) имеют те же самые коды, что и ASCII.

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.