Monday, May 26, 2008

Ain't a typedef


typedefs are a convenient way to give semantics to variables and to stay flexible for future adjustments of the actual used type.

For example if you deal with navigation software you might have some typedefs for Direction and Speed which could be simply ints. And you might have a typedef for Position which is a std::pair<int32_t, int32_t> so that all valid GPS positions of some required resolution can be represented.

Say you want to have some toString or operator<< methods for debuging purposes. So you could have a call trace of your program like this.
std::ostream& operator<<(std::ostream& oss, Direction direction) {
    oss << "Direction=" << int(direction) << " degree";
    return oss;
}

std::ostream& operator<<(std::ostream& oss, Speed speed) {
    oss << "Speed=" << int(speed) << " mps";
    return oss;
}

void someFunction(Speed speed, Direction direction) {
    logger << "someFunction(" << speed << ", " << direction << ")";
    //...
}
and get an output like this
someFunction(Speed=23 meter/second, Direction=42 degree)
Looks good, but doesn't work. If Speed and Direction are typedefed to the same or implicitly castable types the problem manifests:
error: ambiguous overload for 'operator<<'
Unfortunately, altough the keyword is named typedef it is no type definition. The standard says in section 7.1.3:
A typedef-name is [...] a synonym for another type. A typedef-name does not introduce a new type the way a class declaration [...] or enum declaration does.
Prohibition of use of function overloading techniques is just one aspect of the problem. In general you have a type with different semantics but you can not treat it differently. This is a frequent source of annoyance.

PS: Yes, int32_t is not part of ISO-C++. And this is a mistake...

No comments:

Post a Comment