5

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.

Community
  • 1
  • 1
drby
  • 2,619
  • 25
  • 26
  • Do you use arrays of this type for your buffers? Or do you mean that the buffer is 1 single byte long, and you might wish to make it 2 bytes or 4 bytes in future? – j_random_hacker Feb 24 '09 at 12:10
  • In that case, there's not much advantage to using "typedef char bufferElementType;". If you use the same array size everywhere, it may be useful to typedef the entire array type: "typedef char[1024] bufferElementType;" -- that enables you to change the buffer size everywhere in one go. – j_random_hacker Feb 24 '09 at 12:29
  • If however your buffers really are for holding "text characters" and you are considering switching from an exactly-1-byte (e.g. ANSI) character encoding to an exactly-2-byte or exactly-4-byte character encoding, then your original typedef is the way to go. – j_random_hacker Feb 24 '09 at 12:32
  • There is one buffer of the type, but I also perform operations on bytes / chars that are related to buffer (and that don't have the same array length). At the moment I have a constant for the buffer length so I can change that along with the type. – drby Feb 24 '09 at 12:57
  • What I mean is: if the buffer only exists to provide x bytes of storage, what advantage can there be to changing the type of that storage? If you don't do anything type-specific with a buffer, it doesn't matter what type it is. char is usually used because it lets you create buffers of any size. – j_random_hacker Feb 24 '09 at 14:52
  • ... (As opposed to any larger type, which would require the buffer to be a multiple of that type's size in bytes, and probably introduce alignment constraints.) IMHO buffers-of-a-fixed-size-in-bytes are one of the few times when there is no advantage whatsoever to using typedef :) – j_random_hacker Feb 24 '09 at 14:55

3 Answers3

11

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
  • 28,636
  • 4
  • 59
  • 87
  • 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 Feb 24 '09 at 14:45
  • 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 Feb 24 '09 at 16:51
  • 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 Feb 24 '09 at 18:11
2

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
  • 20,752
  • 14
  • 46
  • 53
  • 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 Feb 24 '09 at 14:42
  • I never claimed otherwise. It's much better if the compiler can enforce it itself. But that requires more code. A quick & easy solution is to make it visible to HUMANS - see the linked article for more. – Gilad Naor Feb 24 '09 at 14:50
  • Fair enough. You can avoid accidental direct assignment between types using "class Meter { double _x; public: Meter(double x) : _x(x) {}; operator double&() { return _x; } };" 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 Feb 24 '09 at 18:18
  • (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 Feb 24 '09 at 18:22
1

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
  • 45,516
  • 10
  • 73
  • 79