D needs...

auto ref for non-templates

Currently auto ref only works with templates. A new function/method is generated for each auto ref parameter, depending on whether the parameter is passed as lvalue or rvalue. This results in template bloat, since for each template which uses auto ref parameters, 2^N (whereby N is the number of auto ref parameter) functions/methods are generated:

struct A {
    int id;

    this(int id) {
        this.id = id;
    }
}

void test()(auto ref const A a) {
    writeln("a.id = ", a.id);
}

The test method above would expand to:

void test(const A a) {
    writeln("a.id = ", a.id);
}

if you call it with:

test(A(42)); // by move

and would expand to:

void test(ref const A a) {
    writeln("a.id = ", a.id);
}

if you call it with:

A a = A(23);
test(a); // by ref

As you can see, we have 1 auto ref parameter so the resulting functions are 2^N = 2^1 = 2
The good part is: these methods are only generated if you call the method with either an lvalue or an rvalue. If you call the method only with one of them, only one function is generated. But you can imagine, if you have, let's say, 3 auto ref parameter you would result in 2^N = 2^3 = 8 functions, in the worst case. And: each function contains the whole function body.

There were several attempts and discussions to solve this problem and make auto ref useable without templates. But since this would change the semantic for auto ref for non-template function, auto ref cannot be "abused" for it. An attempt to introduce scope ref / in ref for that (DIP36) was rejected.

Top

negation of attributes

Currently it is impossible to revert / negate attributes. The biggest problem for some D users is the non-existing reversion of final (since D is virtual by default, a common solution is to declare final: on the top of a class, see also final by default).
virtual was shortly introduced [1][2] but then rejected and the PR reverted. That was the start for a (new) forum discussion about the possibility to reverts existing attributes. A few suggested methods were:

!final
~final
final(false)
@disable final

and default [3] to reset the current behaviour to the default. Although attr(false) (e.g. final(false)) seems to fit for the majority, nobody has implemented it until now.

Currently, Daniel Kozak is implementing some variants, like final!(bool), !final, final(bool) and default. Maybe one of them will be the final solution of the problem.

Top

emplacement new

In C++ it is a common practice to reuse your existing memory:

class Foo { };
Foo* f = new Foo();
new (f) Foo(); // reuse existing memory

Since D based on a GC the GC collects your memory and then (eventually) reuse it, but there is (currently) no (easy) way to reuse your memory by yourself.
But thanks to D's capabilities Phobos offers emplace. This function can emplace a object/struct into a given memory chunk. But to reuse your memory you have to write:

class Foo { }
Foo f = new Foo();
f = emplace!(Foo)((cast(void*)f)[0 .. __traits(classInstanceSize, Foo)], ARGUMENTS...);

This is neither safe, nice nor short. And since D wont implement emplacement new like C++, were stuck with emplace.
But we have luck, because a PR is made to introduce an emplace function to simplify the user call:

f = emplace(f, ARGUMENTS...);

Supplement

The PR was rejected, because some users were of the opinion, that emplace is an inappropriate name.
No retry with a different name was made so far.

But you can make such a function by yourself:

T emplace(T, Args...)(ref T obj, aut ref Args args)
    if (is(T == class))
{
    if (obj is null)
        return null;

    enum ClassSize = __traits(classInstanceSize, T);
    void[] buf = (cast(void*) obj)[0 .. ClassSize];
    return emplace!(T)(buf, args);
}

Top

static array literal syntax

D's arrays are a big improvement over the old C Arrays, but they comes with a cost: they are dynamic which means heap allocated. You can, of course, use a static array, but how did you return a static array?

int[3] test() {
    return [1, 2, 3]; // works, but you have to count the elements
}

int[3] test1() {
    int[3] tmp = [1, 2, 3];
    return tmp; // works, but you have to count the elements and get a copy
}

int[] test2() {
    int[3] tmp = [1, 2, 3];
    return tmp; // Error: escaping reference to local tmp
}

int[] test3() {
    return [1, 2, 3]; // works, but this is heap allocated
}

auto test4() {
    return [1, 2, 3]; // works, but this is also heap allocated
}

auto test5() {
    int[3] tmp = [1, 2, 3];
    return tmp; // works, but you still get a copy
}

That's why some D users wanted a way to specify that they want a static array:

auto test() {
    return [1, 2, 3]s; // this is stack allocated
}

Note the s. That would say the compiler "Hey, don't allocate this on the heap, it is only for stack usage".
There were a few discussions and one PR, but the issue was rejected because it is possible to implement such behaviour with the current language features:

@safe
@property
T[n] s(T, size_t n)(auto ref T[n] values) pure nothrow {
    return values;
}

auto test() {
    return [1, 2, 3].s; // this is stack allocated
}

Thanks to the great capabilities of D's UFCS this is possible.

Top

auto length for fixed-length arrays

D's arrays are a big improvement over the old C Arrays, but they comes with a cost: they are dynamic which means heap allocated. You can, of course, use a static array, but you have to count your elements if you want this.

int[] a = [1, 2, 3]; // heap allocated
int[3] b = [1, 2, 3]; // stack allocated

No problem. But if you have more elements it could be annoying to count them. That's why some D users wanted that the compiler does that for them.

int[$] c = [1, 2, 3]; // the compiler detects the dollar and count the elements for us

This was already introduced but then rejected, because it is possible to implement such behaviour with the current language features (see also static array literal syntax):

@safe
@property
T[n] s(T, size_t n)(auto ref T[n] values) pure nothrow {
    return values;
}

int[] c = [1, 2, 3].s; 
writeln(c, ", ", typeof(c).stringof); // prints [1, 2, 3], int[]
auto d = [1, 2, 3].s;
writeln(d, ", ", typeof(d).stringof); // prints [1, 2, 3], int[3]

Thanks to the great capabilities of D's UFCS this is possible.

Top

final by default

In contrast to C++, D is virtual-by-default, like Java. The result is a simple and great possibility to expand your classes, but it gets often forgotten and it has a undeniable impact on the performance of your application.
Therefore some D users wanted final-by-default and a virtual keyword (see also attribute negation). Although it looked like it would be accepted [1] [2] (see alsoDIP 51), it was finally rejected [3], because the code of one Client was affected [4] by this change and D almost lost him.

Yor prevent virtual-by-default you can put final: on the top your your class:

class Foo {
    void test1(); // virtual by default
    final void test2(); // final
}

class Bar {
final: // <- this prevents virtual-by-default
    void test1(); // final
    void test2(); // final
}

The disadvantage is, that (because there is currently no way to revert attributes) you cannot undo it. Instead you can and should mark every method, which is not meant to be virtual, with final

Top