I don't know much about D, but many, many C++ programmers I know greatly dislike it, and I personally have to agree- I don't like the look of D and will not be taking a closer one.
In order to understand why D isn't gaining more traction, you need to start by understanding what attracts people to C++. In a word, the number one reason is control. When you program in C++, then you have complete control over your program. Want to replace the Standard library? You can. Want to do unsafe pointer casts? You can. Want to violate const-correctness? You can. Want to replace the memory allocator? You can. Want to copy around raw memory without regard for it's type? If you really want to. Want to inherit from multiple implementations? It's your funeral. Hell, you can even get garbage collection libraries, like the Boehm collector. Then you have issues like performance, which closely follows control- the more control a programmer has, the more optimized he can make his program. Performance is one of the major reasons to continue using C++.
Here's a few things that I've seen when doing a little research and speaking to a couple of people who have tried it:
Unified type hierarchy. C++ users use inheritance very rarely, most C++ programmers prefer composition, and types should only be linked through inheritance if there is a very good reason for doing so. The concept of Object violates this principle strongly by linking every type. In addition, it's violating one of C++'s most basic principles- you only use what you want. Not being given a choice about inheriting from Object, and the costs that go along with it, are very strongly against what C++ stands for as a language in terms of giving the programmer control over his program.
I've heard about problems with functions and delegates. Apparently, D has both functions and delegates as run-time callable function types, and they're not the same but they are interchangable or... something? My friend had quite a few problems with them. This is definitely a downgrade from C++, which just has
std::function and you're done.
Then you've got compatibility. D is not particularly compatible with C++. I mean, no language is compatible with C++, let's face it, except C++/CLI which is kind of cheating, but as a barrier to entry, it's got to be mentioned.
Then, there are some other things. For example, just read the Wikipedia entry.
pragma(msg, Format!("7! = %s", fact_7));
pragma(msg, Format!("9! = %s", fact_9));
printf is one of the most un-safe functions ever devised, in the same family as big problems like
gets from the old C Standard library. If you search for it on Stack Overflow, you will find many, many questions relating to it's mis-use. Fundamentally,
printf is a violation of DRY - you're giving the type in the format string, and then giving it again when you give it an argument. A violation of DRY where if you get it wrong, then very bad things happen- say, if you changed a typedef from a 16-bit integer to a 32-bit one. It's also not extendable at all- imagine what would happen if everyone invented their own format specifiers. C++'s iostreams may be slow, and their choice of operator may not be the greatest, and their interface could use work, but they are fundamentally guaranteed to be safe, and DRY is not violated, and they can be readily extended. This is not something that can be said of
No multiple inheritance. That's very not the C++ way. C++ programmers expect to have complete control over their program and the language enforcing what you cannot inherit from is a violation of that principle. In addition, it makes inheritance (even more) fragile, because if you change a type from an interface to a class because you want to provide a default implementation or something, suddenly all your user's code is broken. That's not a good thing.
Another example is
wstring. In C++ it's already quite painful to have to convert between them, and does this library support Unicode, and this old C library only uses
const char*, and having to write different versions of the same function depending on the string argument type you want. Notably, the Windows headers, for example, have some extremely irritating macros to cope with the problem that can often interfere with your own code. Adding
dstring to the mix is only going to make things worse, as now instead of two string types, you have to manage three. Having more than one string type is going to increase maintenance pains and introduce repetitive code dealing with strings.
Scott Meyers writes:
D is a programming language built to help programmers address the
challenges of modern software development. It does so by fostering
modules interconnected through precise interfaces, a federation of
tightly integrated programming paradigms, language-enforced thread
isolation, modular type safety, an efficient memory model, and more.
Language-enforced thread isolation is not a plus. C++ programmers expect full control over their programs, and the language forcing something is definitely not what the doctor ordered.
I'm also going to mention compile-time string manipulation. D has the ability to interpret D code at compile-time. This is not a plus. Consider the massive headaches caused by C's relatively limited preprocessor, well-known by all veteran C++ programmers, and then imagine how badly this feature is going to be abused. The ability to create D code at compile-time is great, but it should be semantic, not syntactic.
In addition, you can expect a certain reflex. D has garbage collection, which C++ programmers will associate with languages like Java and C# which are fairly directly opposed to it in philosophies, and the syntactic similarities will bring them to mind too. This isn't necessarily objectively justifiable, but it's something that certainly should be noted.
Fundamentally, it doesn't offer that much that C++ programmers can't already do. Maybe it's easier to write a factorial metaprogram in D, but we can already write factorial metaprograms in C++. Maybe in D you can write a compile-time ray-tracer, but nobody really wants to do that anyway. Compared to the fundamental violations of C++ philosophy, what you can do in D is not particularly notable.
Even if these things are only problems on the surface, then I'm pretty sure that the fact that on the surface, D doesn't actually look like C++ at all is probably a good reason that many C++ programmers are not migrating to D. Perhaps D needs to do a better job advertising itself.