
Hypothetical C++: easy type creation - pierrebai
https://www.spiria.com/en/blog/desktop-software/hypothetical-c-easy-type-creation/
======
crote
Sounds a bit like Haskell's newtype and its class derivation.

Using single-member structs (as explained in [0]) gets you the basic idea, but
that's still missing the automatic lifting of the functions of your underlying
element. I'm not sure if there is a sane way to do this given the current
ecosystem. Perhaps a syntax like `newtype Celsius = int using std::{+, -,
abs}` would work?

[0]: [https://blog.nelhage.com/2010/10/using-haskells-newtype-
in-c...](https://blog.nelhage.com/2010/10/using-haskells-newtype-in-c/)

~~~
jeffdavis
In Rust, using the newtype pattern is fairly common, but doesn't have explicit
support. It's typically done as a single-member tuple.

Maybe support will be added later?

------
ulber
Good discussion and I would love more lightweight type creation in C++.

The "Allow internal functionality" proposal doesn't fully work as-is. Imagine
you have a type Scalar, which has a function:

    
    
      Scalar Scalar::scale(Scalar);
    

If you now do

    
    
      typedecl Scalar Celcius;
    

you'd get a function for it with the following signature:

    
    
      Celcius Celcius::scale(Celcius);
    

However, the function you'd actually want is

    
    
      Celcius Celcius::scale(Scalar);
    

The root problem here is that since the original type mixes different uses of
the type, you can't blindly convert all those uses to the new type.

~~~
pierrebai
This is discussed in the section about including external functionality
through a mechanism of guided mapping. In the proposed syntax, that would be
done like this:

    
    
        typedecl Celsius clone Scalar Scalar::scale(Scalar) -> Celsius Celsius::scale(Scalar);
    

(In the blog post, the example given is with std::pow())

------
svalorzen
These are called "strong/opaque typedefs". There have been multiple proposals
in the past to add them to C++ over the years (N1706, N1891, N3515, N3741,
P0109); the main roadblock is that most people would like to allow to edit a
type's interface after creating the new type (for example, by preventing the
sum of two int-like ProgramVersions), which is for example non-trivial for
primitive types. It should also of course work for non-primitive types, which
introduces lots of interactions with inheritance, templates, and so on.

As another possible way to achieve this, here's the huge proposal to add C++
metaclasses, which I'm personally not really a fan of, since it looks like it
would add an additional third language on top of C++.

Thus, the general opinion is that everybody would like that feature in one
form or another, but it's quite impossible to find a consensus on what the
feature would look like.

~~~
IshKebab
Also called "newtype".

------
mirthless
[https://www.boost.org/doc/libs/1_61_0/libs/serialization/doc...](https://www.boost.org/doc/libs/1_61_0/libs/serialization/doc/strong_typedef.html)

------
mattnewport
There are already units libraries for C++ that go further than this, including
dimension checking (e.g. a velocity type divided by a time type gives an
acceleration typed result with correct units). This extension idea doesn't
seem to offer much over existing library solutions, though it might make
writing those libraries a bit easier.

------
aaaaaaaaaaab
This is already possible even in vanilla C:

Friday Q&A 2013-08-02: Type-Safe Scalars with Single-Field Structs

[https://mikeash.com/pyblog/friday-qa-2013-08-02-type-safe-
sc...](https://mikeash.com/pyblog/friday-qa-2013-08-02-type-safe-scalars-with-
single-field-structs.html)

~~~
IshKebab
Yeah but it is a pain.

------
dilap
A tiny thing, but one of my favorite features of Go. "type FooId int" \-- zero
fuss, zero muss, much clearer and safer code.

