Jump to content

  • Log In with Google      Sign In   
  • Create Account


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.

  • You cannot reply to this topic
29 replies to this topic

#21 0r0d   Members   -  Reputation: 813

Like
0Likes
Like

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:
	// Add your constructors and overloaded operators here

private:
	float mValue;
};

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

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

	return 0;
}


Sponsor:

#22 Álvaro   Crossbones+   -  Reputation: 12922

Like
0Likes
Like

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.



#23 0r0d   Members   -  Reputation: 813

Like
0Likes
Like

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   Crossbones+   -  Reputation: 12922

Like
0Likes
Like

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.



#25 SiCrane   Moderators   -  Reputation: 9560

Like
1Likes
Like

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.

#26 Oberon_Command   Crossbones+   -  Reputation: 1862

Like
0Likes
Like

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.


#27 SiCrane   Moderators   -  Reputation: 9560

Like
1Likes
Like

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.

#28 Hodgman   Moderators   -  Reputation: 29497

Like
1Likes
Like

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.


#29 Servant of the Lord   Crossbones+   -  Reputation: 18498

Like
0Likes
Like

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' 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 - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal

[Fly with me on Twitter] [Google+] [My broken website]

[Need web hosting? I personally like A Small Orange]


#30 Matt-D   Crossbones+   -  Reputation: 1450

Like
0Likes
Like

Posted 21 January 2013 - 01:09 PM

Update: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3515.pdf






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.



PARTNERS