tags:

views:

407

answers:

3

I have a char (ie. byte) buffer that I'm sending over the network. At some point in the future I might want to switch the buffer to a different type like unsigned char or short. I've been thinking about doing something like this:

typedef char bufferElementType;

And whenever I do anything with a buffer element I declare it as bufferElementType rather than char. That way I could switch to another type by changing this typedef (of course it wouldn't be that simple, but it would at least be easy to identify the places that need to be modified... there'll be a bufferElementType nearby).

Is this a valid / good use of typedef? Is it not worth the trouble? Is it going to give me a headache at some point in the future? Is it going to make maintainance programmers hate me?

I've read through When Should I Use Typedef In C++, but no one really covered this.

+11  A: 

It is a great (and normal) usage. You have to be careful, though, that, for example, the type you select meet the same signed/unsigned criteria, or that they respond similarly to operators. Then it would be easier to change the type afterwards.

Another option is to use templates to avoid fixing the type till the moment you're compiling. A class that is defined as:

template <typename CharType>
class Whatever
{
   CharType aChar;
   ...
};

is able to work with any char type you select, while it responds to all the operators in the same way.

Diego Sevilla
I don't understand what advantages using typedef has in this case. The only purpose of the buffer variable is to supply a given number of bytes of storage, and char is always the size of the smallest addressable storage unit. Can you give a scenario where changing the typedefed type would be useful?
j_random_hacker
char to wchar, for example; char to XMLChar (libxml2), etc. I recognize the case of a sole char is not the most interesting, but giving semantically-describing names to types is also a good practice, apart from the other reasons I gave.
Diego Sevilla
Yes, that is one use-case. I got the feeling from the asker's question that he was interested in a buffer of *bytes*, but if it is supposed to hold text characters in some (fixed-size but possibly multibyte) encoding then it's appropriate to consider different buffer element types.
j_random_hacker
+1  A: 

Yes, this is the perfect usage for typedef, at least in C.

For C++ it may be argued that templates are a better idea (as Diego Sevilla has suggested) but they have their drawbacks. (Extra work if everything using the data type is not already wrapped in a few classes, slower compilation times and a more complex source file structure, etc.)

It also makes sense to combine the two approaches, that is, give a typedef name to a template parameter.

Note that as you're sending data over a network, char and other integer types may not be interchangeable (e.g. due to endian-ness). In that case, using a templated class with specialized functions might make more sense. (send<char> sends the byte, send<short> converts it to network byte order first)

Yet another solution would be to create a "BufferElementType" class with helper methods (convertToNetworkOrderBytes()) but I'll bet that would be an overkill for you.

aib
+2  A: 

Another advantage of typedefs is that, if used wisely, they can increase readability. As a really dumb example, a Meter and a Degree can both be doubles, but you'd like to differentiate between them. Using a typedef is onc quick & easy solution to make errors more visible.

Note: a more robust solution to the above example would have been to create different types for a meter and a degree. Thus, the compiler can enforce things itself. This requires a bit of work, which doesn't always pay off, however. Using typedefs is a quick & easy way to make errors visible, as described in the article linked above.

Gilad Naor
typedefs can definitely increase readability, however they can't make errors more visible as they are just aliases that the compiler immediately translates to their underlying type. So if Meter and Degree are both typedefed to double, the code "Meter x; Degree y; x = y;" compiles without errors.
j_random_hacker
Gilad Naor
Fair enough. You can avoid accidental direct assignment between types using "class Meter { double _x; public: Meter(double x) : _x(x) {}; operator double } };" and the same for Degree; but this still allows e.g. "Meter x; Degree y; x = y + 5;". This can also be avoided but is harder.
j_random_hacker
(FTR I deleted two earlier comments that were not very well-thought-out... To guard against "x = y + 5;" you need to define operator overloads for every operator to "stay in the type" as long as possible. This is a lot of work, even more if you want to preserve types across library functions too.)
j_random_hacker