View more

View more

View more

### Image of the Day Submit

IOTD | Top Screenshots

### The latest, straight to your Inbox.

Subscribe to GameDev.net Direct to receive the latest updates and exclusive content.

# A Proposal to Add Strong Type Aliases to the Standard Language

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

29 replies to this topic

### #210r0d  Members

Posted 29 December 2012 - 10:12 PM

So I still dont understand why simply using a class is not an acceptable solution.  You want a new type with your own defined data and behaviors... which is exactly what classes are meant for.

The point is that we don't want to have to write identical classes if we can help it.

Here's another example:
struct Vector3D {
double x, y, z;

Vector3D(double x, double y, double z) : x(x), y(y), z(z) {
}

void print(std::ostream &os) const {
os << '(' << x << ',' << y << ',' << z << ')';
}
};

struct Point3D {
double x, y, z;

Point3D(double x, double y, double z) : x(x), y(y), z(z) {
}

void print(std::ostream &os) const {
os << '(' << x << ',' << y << ',' << z << ')';
}
};


It would be nice to say "a Point3D works exactly as a Vector3D". A typedef would allow that, but then you won't actually get two separate types.

So, like this?

class UnitOfLength
{
public:

private:
float mValue;
};

class Inch : public UnitOfLength {};
class Centimeter : public UnitOfLength {};

int main(void)
{
Inch i;
Centimeter c = i;	// <--- compile error

return 0;
}

### #22Álvaro  Members

Posted 29 December 2012 - 10:47 PM

The constructors don't get exposed when you do that, so you'll have to rewrite them for Inch and Centimeter. Also, you can't do that with primitive types.

Of course there are alternative ways to do this, but having this feature in the language would make certain things easier, that's all.

### #230r0d  Members

Posted 29 December 2012 - 11:35 PM

The constructors don't get exposed when you do that, so you'll have to rewrite them for Inch and Centimeter. Also, you can't do that with primitive types.

Of course there are alternative ways to do this, but having this feature in the language would make certain things easier, that's all.

Ahh, that's right, I forgot that the constructors and operators wont be inherited and you'll need to declare them in the child classes.

Ok, I can see where the motivation for this comes from, but on the other hand I've never seen a real case where I'd save enough typing/code duplication to make me want this.  In the Inch/Centimeter example, it's only 2 classes.  But even if more, this is stuff that you write once and then it'll sit in a lib untouched afterwards.  And, with a class you do get the additional abilities like operator overloading, and controlling which ones to allow and which to not allow.

In the code sample you gave... it just seems out of control.  You really just need a single 2D Point object (you have 13!), but somehow it looks like you're trying to prevent your high-level code from doing the wrong thing by moving your error checking to the lowest levels, and in doing so actually making more work for yourself with all these different typedefs that all cant be automatically cast to each other.  If I saw this code anyplace I worked I'd seriously have to wonder what the heck was going on.

### #24Álvaro  Members

Posted 30 December 2012 - 06:20 AM

In the code sample you gave... it just seems out of control.  You really just need a single 2D Point object (you have 13!), but somehow it looks like you're trying to prevent your high-level code from doing the wrong thing by moving your error checking to the lowest levels, and in doing so actually making more work for yourself with all these different typedefs that all cant be automatically cast to each other.  If I saw this code anyplace I worked I'd seriously have to wonder what the heck was going on.

I guess that paragraph was responding to SOTL, not me. I'll reply anyway.

I have to admit that those 13 classes seem a little overwhelming, but I don't see his code as moving error checking to the lowest levels. It is simply making the type system work for him, by forbidding operations that are most likely bugs. I can see myself doing something similar for vertices in a 3D pipeline: If you add model coordinates and world coordinates together, you probably have a bug, and having separate types for them makes total sense.

At work we deal a lot with orders to buy or sell stocks. Whenever I use a double in that context, I actually know more about it than that: It's an order size in shares, or a price in dollars/share, or a price in euros/share, or a dollar value for the order (or sometimes more exotic things, but let's keep it simple). It would make total sense to use separate types for these things, although in the end they are all just doubles when you get down to assembly level. I just would like my compiler to bomb if I ever try to add a quantity and a price.

### #25SiCrane  Moderators

Posted 30 December 2012 - 10:27 AM

Ahh, that's right, I forgot that the constructors and operators wont be inherited and you'll need to declare them in the child classes.
Though see n2141 and forwarding constructors in C++11.

### #26Oberon_Command  Members

Posted 30 December 2012 - 03:51 PM

Also, you can't do that with primitive types.

You could always write a "boxed type" template class that encapsulates a primitive type, while supporting the same operators the primitive type does. So, essentially reinventing Java's "boxed types" in C++ using templates. I'm not in a position to say whether that would be worth the effort, though. My guess would be that it isn't.

Edited by Oberon_Command, 30 December 2012 - 03:52 PM.

### #27SiCrane  Moderators

Posted 30 December 2012 - 04:15 PM

Well, it's a common enough situation that there's a boost library for simplifying the creation of new arithmetic types.

### #28Hodgman  Moderators

Posted 01 January 2013 - 08:21 AM

You could always write a "boxed type" template class that encapsulates a primitive type, while supporting the same operators the primitive type does. So, essentially reinventing Java's "boxed types" in C++ using templates. I'm not in a position to say whether that would be worth the effort, though. My guess would be that it isn't.
I have one of those in my engine, which acts like the type (operator wise), but with an explicit constructor from that type.
e.g. short version:
template<class T, class Tag> struct P
{
P() : value() {}
explicit P( T v ) : value(v) {}
T value;
};
struct MetreTag {};
struct InchTag {};
typedef P<float, MetreTag> Metre;
typedef P<float, InchTag> Inch;
And then I write conversion functions like:
Inch ToInches(Metre m) { return Inch(m.value * 39.3700787f); }
void test()
{
Metre m(10);
Inch i( ToInches(m) );
Inch error( m );//won't compile
}
I haven't used the boost solution, but I imagine it's similar to this, so I probably suffer from the same issues that SOTL found with boost's version.

Edited by Hodgman, 01 January 2013 - 08:25 AM.

### #29Servant of the Lord  Members

Posted 01 January 2013 - 09:06 AM

Your version looks great for basic types (which mine doesn't support), but doesn't support classes (which mine does).

Most of my strong aliases have to do with a basic 'Point' type.

I could write a template just for points, but I figured in such a strongly-typed language as C++, why not have a generalized solution built into the language?

We did so for enums with the C++11 'enum class'.

It's perfectly fine to abbreviate my username to 'Servant' or 'SotL' rather than copy+pasting it all the time.
All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.
Of Stranger Flames -

### #30Matt-D  Members

Posted 21 January 2013 - 01:09 PM

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.