views:

87

answers:

5

Background:

I have template stream operators (e.g. operator << (ostream &, std::vector <T>)) (that output container elements that may possibly be of some 8-bit integer type, (e.g. unsigned char, int_least8_t, et cetera).

Problem:

Default is that these types are output as char (ASCII). I only used char (or wchar_t or whatever) for ASCII variables, never unsigned/signed types. How do I get these other 8-bit types to always be output as signed int / unsigned int (numbers) instead, even when the caller doesn't know the type?

First tries:

I have tried (with GCC) for example defining operator << (ostream &, unsigned char) with a cast in it (i.e. stream << static_cast <int> (value). That works for unsigned char values, but then uint8_t still gets output as a char.

The same underlying type (i.e. unsigned/signed char can not be used in overloads, so I can't define an overload of for example operator << (ostream &, int_fast8_t).

+1  A: 

If I have understood you right.. output it like this:

std::cout << ( unsigned int )char << '\n';

Or more c++ style - use static_cast, for example:

int main()
{
    char a = 'a';
    char b = 97;
    std::cout << static_cast< unsigned int >( a ) << '\n';
    std::cout << static_cast< unsigned int >( b ) << '\n';
    return 0;
}

both std::cout will print the same: the first one - the ASCII code of 'a': 97, the second one - just the value 97, stored in b. Both, a and b, are absolutely the same.

Kiril Kirov
+1 I understood the same. Not sure though xD
Santiago Lezica
10x, anyway xD It would be really nice, if posters explain themselves with examples (:
Kiril Kirov
It's not easy when you have this kind of question. It happens to all of us: if we were really able to describe with accuracy our problem, we would've already found a solution to it. I ended up answering to see if I could explain a bit further xD
Santiago Lezica
Yep, you right, but what I meant was, that the poster could say: "for example, if I have stored a value `97` in an unsigned char, how to print it as the number `97`, instead of printing `a`." But you're absolutely right, this is not always possible (y)
Kiril Kirov
+1  A: 

One way that comes to mind is using type traits to define the output type for each type. You would have to declare that for every type by hand. The traits could be defined as a template struct that is specialized for every data-type that has a different output-type than the data-type itself:

template< T >
struct output_trait {
    typedef const T & output_type;
}

In your operator you write:

std::cout << static_cast< output_trait< T >::output_type >( variable ) << std::endl;

This will do no cast by default, but for types for which output_trait is specialized it will do a cast:

template<>
struct output_trait< unsigned char > {
    typedef unsigned int output_type;
}
Space_C0wb0y
@sbi: Indeed I did. Fixed.
Space_C0wb0y
Thanks, I would never have guessed that myself. (The other answers completely missed the part about the template container.)
stellarvortex
+1  A: 

You can simply cast it:

#include<iostream>

int main()
{
 uint8_t blah = 65;
 std::cout << static_cast<int>(blah) << "\n";
 return 0;
}

65

Merlyn Morgan-Graham
A: 

You can cast them before you output them:

std::cout << (unsigned int) container[index];
bjoernz
container doesn't mean "string" or array, or sth. It means an object, that contains other objects/vars. So, if you have a struct with two chars inside, you can't output them like this (:. Anyway, I didn't down-vote your answer, as I understood what you mean, but don't mix the terms, please (:
Kiril Kirov
thanks for clarifying. I just tried to give a minimal, abstract example. When I started writing my answer the other (better!) answers were not there.
bjoernz
+2  A: 

You're confusing the actual data held in a variable, with whatever representation you choose for printing it.

Think of it this way: chars, ints, doubles, longs, whatevers, they're all just chunks of memory for you to store numbers in. A char is a number between 0 and 255 (or -128 and 127) -- you can choose to represent it as an ASCII character, or as a number, or as stars in the sky with the aid of OpenGL.

If you want to see the number behind the character 'a', just instruct your program to treat that chunk of memory (that for you contains an 'a') as a number. Use casts. Here:

http://www.cplusplus.com/doc/tutorial/typecasting/

See if that helps!

Santiago Lezica
`+1` for addressing the underlying confusion of the OP, rather than showing which syntax to use.
sbi