Note: I guess I'll get flamed for this, but, then, it is a C++ question for C++ developpers, so...
What are the things that can be done in C but not in C++, and which of these features do you miss the most while coding in C++?
As a C++ developer, I miss nothing from C, be it C99 or otherwise.
I do not write this just out of spite. This is a question for C++ developers who miss some C/C99 features because they ignore basic features of C++. I do believe the question and its answers ignore viable or better alternatives in C++ (and no, the "C++ vector are nasty" comment is just a bogus reason).
This is why I will discuss here each one of the supposed "missing features"...
Variable-length arrays?
Variable length arrays is a language feature of C99. Its key advantages are:
- allocation on stack
- variable length on creation
- no need to deallocate
For the most common cases, std::vector
will do the job, and have more features anyway. For example, unless I'm wrong, the variable-length array have the following disadvantages:
- allocation on the stack means you can't return a VLA from the function where it was declared
- the VLA can't be resized, meaning that if it's too small, then you're screwed
- VLA must be either declared at prototype scope, or block scope. It can't be extern, or static. And you can't declare it as a member of a struct.
- It cannot have an initializer
The vector can be resized, and can be returned. And with C++0x (and the r-value references), you can return a vector using move semantics, meaning no useless temporary object is needed. You can put it in a struct/class, it can be extern, or static. you can initialize it with a default value, the content of an array, a container, or, with C++0x, with an initializer list.
And even after that, if you really want something like the VLA, in C++, it is possible for an average C++ developer to write a stack-based vector-like container. And it would not need a full language committee update for that.
Just for the fun, I happened to post an answer with a simple proof-of-concept of a C++ VLA-like class.
C++'s vector is most of the time a better alternative, with more features. And in the rare case a VLA is really really needed, its features could be emulated by a user-defined class.
Casting void *
into T *
?
As for casting any void *
into another typed pointer, this is not a feature of C missing from C++: This is a choice of weak-typing vs. strong-typing
And it's not as if it was impossible to do it in C++, as you can do it with a cast. The point of this difference is to decrease a bug risk in a language where void *
is not as useful as in another: In my current C++ 100k lines project, I have zero occurrences of void *
.
Designated initializers?
Constructors offers a better alternative.
Of course, you don't get the possibility of initializing directly the data in the struct, but then, data encapsulation means that most of the time, the data in my objects are private, so, the whole concept of using designated initializers to initialize them would be ridiculous.
As for POD-like structures, well, a constructor is easy to write, and can handle cases designated initializers won't ever do (like initializing members with non-zero values by default, or even calling functions).
Because C++'s focus on data encapsulation, constructors offer a better alternative to designated initializers.
Compound Literals?
This syntactic sugar supposes, again, that you know both the exact implementation of the struct, and have a public access to its members, which is something you usually want to avoid in C++.
Once again, Compound Literals are not something that can't be handled by a function, method or even constructor, with the advantage of bonus features, as described above.
Declare variable names that are keywords in C++ but not C?
I know how you feel: Each time I have the possibility of using interface
, final
or synchronized
in C++, I get Java shivers, too...
:-P
Type-generic macro?
The problem in C is that you have quite a bunch of functions, doing the same semantic thing to different types, meaning the each function must have a different name. For example, according to the OpenGroup, the following functions do exist:
double sin(double x);
float sinf(float x);
long double sinl(long double x);
- etc.
Source: http://www.opengroup.org/onlinepubs/009695399/functions/sin.html
But their names are a real pain to remember, so someone had an idea. Something about a macro which would use a compiler built-in extension to call the right one according to the types of the used parameters.
This is all the magic of C99's <tgmath.h>
.
And the idea seemed so awesome that they even added a proposition to offer this feature for all functions in the next C standard, with something like:
#define sin(x) __tgmath(x,,, \
float, sinf, long double, sinl, \
/* etc. */ \
, , sin)(x)
Source: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1340.htm
Now, the shocking news: This features is available in C++ since decades: This is called function overloading.
For example, the functions above are declared in C++ as:
double sin (double x );
float sin (float x );
long double sin (long double x );
- etc.
So, the "Type-generic macro" is a hacked implementation, which strives to (partially) emulate the more generic C++ function overloading.
And guess what: You can even add your own overloads for your own user-defined types.
Conclusion
As shown above, each time I study a C99 feature, the conclusion is: "Hey, I already could do that in C++!" (and usually with the word "better" somewhere in the sentence).
Seriously, as a C++ developer, what I miss right now is to be able to use C++0x at work. For example, the following C++0x features:
auto
constexpr
- initialized lists
- r-value references
- lambdas
nullptr
- etc.
The whole "C missing features from C++" is an overrated concept which, I suspect, is more interesting to C developers (and C-with-classes developers) than C++ developers.