3 ms·
Or for that matter, the C++11 concurrency primitives, smart pointers, type inference (auto), nullptr, lambdas, static_assert, <regexp>, stuff like http://libsig
by codewright 14y ago
Or for that matter, the C++11 concurrency primitives, smart pointers, type inference (auto), nullptr, lambdas, static_assert, <regexp>, stuff like http://libsigc.sourceforge.net/ http://libsigc.sourceforge.net/
List goes on...
- cmccabe 14y agoLanguage flamewars are dull. Very dull. But since you gave specifics, I will too. Concurrency primitives in C: it's a library issue. In userspace, use libatomic-ops. In kernel space, you've got atomic_t and it works well. static_assert: the kernel has BUILD_BUG_ON. You can easily roll your own in userspace in a line or two. It should get added to C at some point, but it's not a huge issue. type inference via "auto": C++ only needs this because it adopted the "stutter" syntax 30 years ago. "Foo foo = new Foo()" is not something you see in C. nullptr: C++ only needed this because it had function overloading. Since NULL is actually just a macro for 0, it easily matches functions where it "shouldn't". C doesn't need this hack. Note that you still have the "pointer to bool" conversion path in C++-- have fun with that. (C doesn't have bools.) lambdas: gcc has supported nested functions in C for a while. Not too many people use them because honestly, they are not that useful in C, as good as they may be in other languages. regexp: there's a ton of libraries out there for doing regular expressions in C. PCRE is a well-known one. Or even just regex.h. However, if you find yourself using this a lot, it might be a warning that you're using the wrong language for the job. parametric polymorphism: now we're getting closer to the heart of the issue, aren't we? A lot could be written about this, but let me just say this: the C++/Java type system leans heavily on inheritance, which is an antipattern. C tends to encourage you to use composition, which is the right way to do things anyway. You can create vtables of function pointers in C when you really need to, which isn't as often as a lot of Java/C++ programmers have been trained to think.
- frou_dh 14y agoThe mindset you're talking about is reliance on subtype polymorphism, which is something different. I'm not in to inheritance either. What I meant is a better level of abstraction than void star and/or macro abuse.
- electrograv 14y ago> "Foo foo = new Foo()" is not something you see in C. In C++: "Foo *foo = new Foo()" In C: "Foo *foo; foo = malloc(sizeof(*foo));" C stutters even more, unless you want to use macros to 'patch' the stutter, but that applies to both languages equally. You're right that there's no need for flamewars. I agree with most C programmers in style, as I am a C programmer at heart. I program C++ code that looks like simpler, cleaner C code. Why does it look simpler and cleaner? Because I don't have to typedef my structs or stutter "struct" everywhere. Because I have templates to reduce that "necessary code duplication" where it matters for performance. I have constructors and destructors for the cases where I need compiler-enforced init/destroy function calls within a {} scope. I have references so I can almost entirely eliminate the worry of null pointer values in my code. The point is that C is not the subset that most people want. Being a smaller subset of C++, it has a lot of appeal to me. But ultimately, there are genuinely useful C++ syntax features that can make your life much easier in producing reliable, clean code. Absolutely C++ can be abused (i.e. inheritance for anything but interfaces), and absolutely C++ has some annoying quirks. That doesn't bother me too much, because at the end of the day C++ leads to cleaner code and higher productivity for me due to these relatively "syntactic sugar" features that I use.
- cmccabe 14y agoYou say "C stutters even more" but your example is not an apples-to-apples comparison. You split the C version up into two lines, whereas the C++ version is one line. The issue really is that type names tend to be a lot longer in C++ than they are in C, and so the "same" amount of reptition hurts a lot more. auto will help with this a little bit. But you're still going to end up using typedef a lot to shorten those type names. Especially for anything where you're using an iterator. Trust me, I've been there. typedef'ing structs is an anti-pattern in C. See http://www.kernel.org/doc/Documentation/CodingStyle http://www.kernel.org/doc/Documentation/CodingStyle. Basically the rationale is that the fact something is a struct is useful information which should be reflected in the type name. So you use constructors and destructors. Good job, but how to you report errors from those constructors and destructors? Even if you're willing to use exceptions (and most experienced C++ users, like Google, Mozilla, etc are not), you can't safely throw one from a destructor, because of the risk of triggering std::terminate. So you usually end up writing your own init() and shutdown() functions for most non-trivial classes anyway. But you still have to define the useless constructor anyway, because hmm, C++ doesn't see fit to zero your class fields of POD type. Now don't try using memset-- you know better than that. Better specify what you want to initialize each one to individually in a long assignment list. And let's not forget to define a copy constructor and an assignment operator, or else you'll get screwed when someone copies your class bit-wise and does a double free. Sound familiar? This is all adding up to a lot of boilerplate that you wouldn't have to deal with in C. Syntactic shackles is more like.