Implicit conversions in user types

From D Wiki
Jump to: navigation, search

Part of D's philosophy is that the gap between builtin types like int, char, and string, and user-defined types, like BigNum, should be as narrow as possible. This is especially true for user-defined numeric types, which ideally should blend into the language's expression syntax so that, besides actually declaring a variable of the user-defined type, it can be used just as if it were a built-in type.

An important component of narrowing the gap between builtin and user-defined types is permitting implicit conversions between the user-defined type and the builtin types. For example, it is desirable for a custom integer type, say MyInt, to implicitly convert to the builtin int type, so that if you have a function func that expects an int, you can directly pass MyInt to func without having to explicitly call a conversion function to convert MyInt to int.

One way to accomplish this implicit conversion is to use D's alias this feature:

struct MyInt
{
    @property int toInt()
    {
        // perform necessary computations to convert MyInt to int
        return convertedValue;
    }

    alias toInt this;
}

void func(int x) { ... } // N.B. expects an int

auto mi = MyInt();
func(mi.toInt);   // this works, but is ugly
func(mi);         // this also works, because of alias this

This technique works because alias X this means that the struct MyInt will behave like X, except that it adds a few members of its own. In this case, X is toInt, which happens to be an int property, which means that MyInt should behave like an int. When MyInt is passed to func, the compiler evaluates the property toInt, but since that's a @property, this turns into a function call to toInt() that performs the desired conversion. Implicit conversion to int is thus achieved.

This technique can be used to implicitly convert to any desired type.

Real-world examples

A nice application of the presented technique is in implementing a half-precision floating point type. See e.g. one of the related discussions on the digitalmars.D forums and a working prototype by Walter Bright.