News for hackers. Stuff that matters.
Re:Why C++ sucks (2016 edition) by Negitivefrags on Monday February 22, 2016 @03:49AM (#11149459)
You know what? I'm going to take the controversial opinion that C++ is both the best tool for everywhere and my favorite language.

C++ really has only one downside. It's hard to learn. Almost all complaints about it really boil down to not knowing the language well enough.

But so what? Because once you know it well...

Once you know C++ really well, you understand what it means to have no compromise.

It has the best performance and the highest level abstractions in one package.

It has both amazing safeguards against programmer error and the ability to break all of them if you need to.

It has great portability while still giving you full access to all he platform specific features.

You can feel just as at home writing a web browser or a website in C++.

I could go on.

You get all this good stuff and really it only really takes a few years of seriously using the language to get that good. What is a few years in a 40 year career?

Also, don't believe the bullshit of "nobody really knows C++" that a lot of people claim. You can find dark corners of any language. The reason they are dark corners is because they don't come up in real code.

Re:Why C++ sucks (2016 edition) by pistacchioso on Monday February 22, 2016 @06:54AM (#11150193)
Hm, no, it sucks. "I can do that with ease because I've done it so many times" is really a terrible argument to explain why something is good. If you've lost a leg, walking with a crutch becomes second nature to you, but that doesn't mean that's the preferred or most efficient way of walking for the human being.

Yes, you know by heart that all_of requires "foo.begin()" and "foo.end()" and the capture context "[]", but it doesn't negate the fact that many other, better languages, just know how to cycle an array without having to specify begin and end, know how to capture arguments when needed, don't require a useless (in this context) return, nor clutter a single line of code with nine differenct gibberish symbols like "(", ")", "::", ",", "[]", ";" "{", "}".

Take the ultra humble javascript: foo.every(a => a % 2)

When you need three times the characters to obtain the same result, and those charcters are a clusterfuck, it is not relevant if years of usage made you comfortable nonetheless with it.

Re:Why C++ sucks (2016 edition) by masklinn on Monday February 22, 2016 @07:09AM (#11150257)
> know how to capture arguments when needed

Not to take away from your other criticisms, but in most languages how the arguments are captured has no relevance (in Javascript — and most every other managed language — the environment is always captured by reference and the GC handles lifetimes of "whatever"), whereas it is very relevant and important for C++. So I think that part of the criticism is unwarranted.

Though Rust didn't go to the same lengths[0] you still have to specify whether the environment is captured by reference (the default) or by value (`move` lambdas), because that can have a large and semantic impact on the system.

[0] see https://www.reddit.com/r/rust/comments/46w4g4/what_is_rusts_... for the impressions of a C++ developers wrt what it sees as corners cut, and replies by rust devs showing these corners turned out to be mostly unnecessary in rust

Re:Why C++ sucks (2016 edition) by hnbro on Monday February 22, 2016 @07:40PM (#11155546)
i think having known bounds would make arrays a non-zero cost abstraction.
Re:Why C++ sucks (2016 edition) by raverbashing on Monday February 22, 2016 @04:16AM (#11149556)
> C++ really has only one downside. It's hard to learn. Almost all complaints about it really boil down to not knowing the language well enough.

Did you read the link and the examples shown (std::chrono one, for example)

Yeah, in the time I go around trying to solve C++ self-inflicted tangles I can learn Go or code stuff in Python (or even Java/C#) which 99% of the cases is fast enough

I used to advocate for complex stuff, but now I think differently. Solve my problem, I don't care about religious issues.

Re:Why C++ sucks (2016 edition) by quarktasche on Monday February 22, 2016 @05:46AM (#11149909)
I don't think the std::chrono example is fair at all.

In the C++ case, you specify which clock you want. What kind of clock is DateTime.UtcNow()? Is it monotonic? What's the resolution? It's maybe in the documentation, but if the author refuses to remember simple syntax, surely he won't want to remember such details either.

The author also chose an example where he abuses the default behavior in the C# case. The last line in the C++ example just vanishes if you use the default behavior in both cases.

Re:Why C++ sucks (2016 edition) by gpderetta on Monday February 22, 2016 @06:13AM (#11150016)
Also std chrono is very strict with types: time points and durations can't be freely mixed, milliseconds and microseconds have different types [1] and you can't implicitly convert from a float based time to an integer based time.

Does C# do the same thing?

[1] the underlying type actually encodes the exponent as a non-type template parameter. Converting from ms to us correctly applies the multiplicative factor.

Re:Why C++ sucks (2016 edition) by ygra on Tuesday February 23, 2016 @03:57AM (#11157506)
> Does C# do the same thing?

To some extent. Points in time (DateTime) and durations (TimeSpan) cannot be mixed either, although you can subtract two DateTimes and get a TimeSpan, or add a TimeSpan to a DateTime. But I guess those work in C++ just as well.

Internally they are all based on ticks, which are 100-ns intervals (in DateTime since 0001-01-01) stored as a signed 64-bit integer. Different quantities of time don't need different types because there's only one type that represents a duration.

Re:Why C++ sucks (2016 edition) by chris_wot on Monday February 22, 2016 @09:01AM (#11150797)
But with any complex interface, wouldn't it be a good idea to introduce a less complex facade that only deals with common usecases, and for complex use cases use that underlying interface?
Re:Why C++ sucks (2016 edition) by gpderetta on Monday February 22, 2016 @09:50AM (#11151087)
The whole point of the complexity chrono interface is to prevent mistakes caused by accidentally mixing different units. Providing a default unsafe interface would completely defeat the point.
Re:Why C++ sucks (2016 edition) by masklinn on Monday February 22, 2016 @10:27AM (#11151405)
That an interesting point of view to take in defence of C++ of all things.
Re:Why C++ sucks (2016 edition) by gpderetta on Monday February 22, 2016 @12:20PM (#11152449)
Sorry, I might misparsing your replay, but are you saying that std::chrono is overly strict? Or that because C++ (and its C heritage) has allowed unsafe implicit conversions in the past, it should continue doing it in the future?
Re:Why C++ sucks (2016 edition) by masklinn on Monday February 22, 2016 @01:36PM (#11153124)
Just that it feels strange to see safe defaults/interfaces used to argue for C++, nothing more.
Re:Why C++ sucks (2016 edition) by fsloth on Monday February 22, 2016 @10:24AM (#11151374)
"I can learn Go or code stuff in Python (or even Java/C#) which 99% of the cases is fast enough I used to advocate for complex stuff, but now I think differently. Solve my problem, I don't care about religious issues."

This sounds like it's written in the hobbyist/lone tinkerer/ deploying to self managed server context.

When discussing could anything replace C++ one is usually in the context of a massive business environment pending on millions of lines of C++ and native bindings, not figuring out how to write a handy personal tool.

For handy personal tools, Python is probably much better than C++ 99% of time, but when discussing, how to replace a language in an entrenched ecological slot with a huge number of interdependencies things are really not that simple at all.

Re:Why C++ sucks (2016 edition) by autoreleasepool on Monday February 22, 2016 @09:09AM (#11150844)
> Python and Go

> 99% of the cases is fast enough

This claim is unsubstantiated hyperbole.

Re:Why C++ sucks (2016 edition) by hnbro on Monday February 22, 2016 @06:43PM (#11155288)
how dare they.
Re:Why C++ sucks (2016 edition) by autoreleasepool on Monday February 22, 2016 @06:53PM (#11155336)
Right, bro? That's what I'm saying. Misinformation is no bueno
Re:Why C++ sucks (2016 edition) by alkonaut on Monday February 22, 2016 @04:26AM (#11149598)
> C++ really has only one downside. It's hard to learn

I don't think the article lists just one downside. For example It's also undeniably hard to parse, making it harder than necessary impossible to implement efficient refactoring tools and other parser dependent tools, for example.

> It has both amazing safeguards against programmer error and the ability to break all of them if you need to.

C++ has two main design constraints -- it comes from C and its abstractions should cost nothing. Those two have enormous benefits and drawbacks. Performance is one thing. Other languages that don't have those design goals/constraints have different benefits and drawbacks. It's easier to make a small shell util or in perl/python than in C++. It's easier to make a formally verified system in a functional lang than in C++ and so on. "The best tool for everywhere" meaning "if you need to use the same language to solve all N problems then C++ is best of the major and widely used languages" might be true, but it's also a pretty poor metric.

Re:Why C++ sucks (2016 edition) by jcelerier on Monday February 22, 2016 @05:58AM (#11149960)
> For example It's also undeniably hard to parse, making it harder than necessary impossible to implement efficient refactoring tools and other parser dependent tools, for example.

http://clang.llvm.org/docs/Tooling.html

Re:Why C++ sucks (2016 edition) by autoreleasepool on Monday February 22, 2016 @09:12AM (#11150853)
I'm curious, what languages have better support for tooling than C++?
Re:Why C++ sucks (2016 edition) by Sindisil on Monday February 22, 2016 @09:48AM (#11151067)
Java is an obvious example.
Re:Why C++ sucks (2016 edition) by autoreleasepool on Monday February 22, 2016 @01:20PM (#11152987)
I can think of several areas where Java support for tooling is unobviously superior when compared to C++.

The SDK for the Arduino is good example, so is the Unreal game engine, the tooling support in Xcode for iPhone Apps, the support for static analysis via Clang, the auto formatting support via clang-format, the support in Windows eith Visual Studio, the support for autocompletion in UNIX text editors such as Vim and Emacs with the YouCompleteMe daemon and client (which leverages clang).

So if Java is an example of superior tooling, it's not really an "obvious" one

Re:Why C++ sucks (2016 edition) by hnbro on Monday February 22, 2016 @07:15PM (#11155436)
perhaps "unobvious" to you, but that's something which is empirically (if subjectively) resolvable, no?
Re:Why C++ sucks (2016 edition) by autoreleasepool on Monday February 22, 2016 @08:39PM (#11155823)
My bro, it's truly an honor to have my first HN comment stalker. I feel like I finally made it
Re:Why C++ sucks (2016 edition) by hnbro on Tuesday February 23, 2016 @11:21AM (#11159927)
a coincidence, but whatever.
Re:Why C++ sucks (2016 edition) by hellofunk on Monday February 22, 2016 @04:16AM (#11149555)
I completely agree. I very much enjoy working in it, even after 2 years of exclusively Clojure development, I had no problems coming back to modern C++ with all its lovely functional tools and enjoy every moment of it.
Re:Why C++ sucks (2016 edition) by autoreleasepool on Monday February 22, 2016 @09:08AM (#11150835)
> The reason they are dark corners is because they don't come up in real code.

Thank you!

It's amazing how much FUD is spread using examples that would never pass code review! (or even be submitted to code review unless you were playing a prank on your coworkers).

Re:Why C++ sucks (2016 edition) by loup-vaillant on Monday February 22, 2016 @04:22AM (#11149579)
> It has the best performance and the highest level abstractions in one package.

The highest level abstractions, are you kidding me?

I am currently writing a little interpreter in C++. I would have used Ocaml, but the rest of the project is in C++. Well, just try to write an abstract syntax tree in C++. In languages such as ML and Haskell, this is easy:

  type expression = Litteral    of value
                  | Symbol      of string
                  | Funcall     of expression * expression
                  | Conditional of expression * expression * expression
                  | While_loop  of expression * expression
                  | Sequence    of expression list
And I'm pretty much done. Now in C++:

  --------------------------------------------------------------------------------
  #ifndef __Expression_h__
  #define __Expression_h__
  
  #include <cstdint>
  #include <string>
  #include "Value.h"
  
  
  namespace Script {
  
  class Expression;
  
  class Expression {
  public:
      enum Tag {
          litteral,
          symbol,
          funcall,
          conditional,
          while_loop,
          sequence
      };
  
      union Val {
          Value                   *litteral;
          std::string             *symbol; // or a true symbol?
          std::vector<Expression> *composite;
      };
  
      Expression(const Value&);
      Expression(const std::string&);
      Expression(Tag, std::vector<Expression>*); // takes ownership
      ~Expression();
  
  private:
      Tag _tag;
      Val _val;
  };
  
  } // namespace Script
  
  #endif // __Expression_h__
  --------------------------------------------------------------------------------
Don't forget the cpp file either:

  --------------------------------------------------------------------------------
  #include "Expression.h"
  #include <cstdio>

  using namespace Script;
  
  Expression::Expression(const Value& val)
      : _tag(litteral)
  {
      _val.litteral = new Value(val);
  }
  
  Expression::Expression(const std::string& sym)
      : _tag(symbol)
  {
      _val.symbol = new std::string(sym);
  }
  
  Expression::Expression(Tag tag, std::vector<Expression>* exprs)
  {
      if ((tag == funcall     && exprs->size() == 2) ||
          (tag == conditional && exprs->size() == 3) ||
          (tag == while_loop  && exprs->size() == 2) ||
          tag == sequence) {
          _tag = tag;
          _val.composite = exprs;
      } else {
          std::fprintf(stderr, "Expression constructor: Invalid Expression\n");
          exit(1);
      }
  }
  
  Expression::~Expression()
  {
      switch (_tag) {
      case litteral   :
          delete _val.litteral;
          break;
      case symbol     :
          delete _val.symbol;
          break;
      case funcall    :
      case conditional:
      case while_loop :
      case sequence  :
          delete _val.composite;
          break;
      default:
          std::fprintf(stderr, "Expression destructor: broken class invariant\n");
          exit(1);
      }
  }
  --------------------------------------------------------------------------------
I may use smart pointers instead of doing my own RAII by hand, but that's still a hassle. Some may point out that my ugly unsafe union type is not the way to to this, I should use a class hierarchy and polymorphism. But just imagine the sheer amount of code I'd have to write.

C++ is a low level language. It's high level pretense is nothing but a thin veneer that cracks under the slightest scratch. Or, someone show me how to implement an abstract syntax tree in less than 20 lines of code. I'm lenient: Haskell and ML only need 6.

(Yes, I'm using Sum types, a feature that's pretty much unique to ML languages. But no, that's not cheating: providing enumeration and unions but somehow failing to combine them into sum types is a serious oversight.)

Re:Why C++ sucks (2016 edition) by userbinator on Monday February 22, 2016 @04:48AM (#11149686)
I think you're deliberately making it more verbose than it needs to be. The class definition could be condensed into:

    class Expression {
      enum Tag { litteral, symbol, funcall, conditional,
       while_loop, sequence } _tag;
      union {
       Value *litteral;
       std::string *symbol; // or a true symbol?
       std::vector<Expression> *composite;
      } _val;
    };
And you could probably use templates or macros to autogenerate most of those constructors/destructors automatically.
Re:Why C++ sucks (2016 edition) by loup-vaillant on Monday February 22, 2016 @05:12AM (#11149772)
> I think you're deliberately making it more verbose than it needs to be.

I swear I am not. This is will be production code, for which I earn my salary. Your code is terser, but still fundamentally the same as mine. It's still unsafe (we could access the wrong union member), and it still has to work around incomplete definitions and the lack of trivial constructors (I wouldn't use pointers otherwise).

Automating my constructors and destructors would be amazing. Unfortunately, I don't know how to do it —not without writing over a hundred lines of cryptic boilerplate first.

Re:Why C++ sucks (2016 edition) by fsloth on Monday February 22, 2016 @05:10AM (#11149763)
The ML example was missing the second half of the ML niceness - efficient pattern matching at syntax levels which makes for a really nice and understandable code, especially when writing complex compound clauses.

"...could probably use templates or macros to autogenerate.."

... which kind of highlights that ML example even more. In Ocaml or F# that original definition would have been more or less enough to start writing nice, efficient parsing code.

The sum types are not the only thing, IMO, that ML-family has going for it. As for example F# contains pairs and lists as syntax level constructs (rather than library add-ons) lot of code can be written at a really high level before optimization - in the same language - if it's needed.

Re:Why C++ sucks (2016 edition) by jcelerier on Monday February 22, 2016 @06:04AM (#11149982)
Re:Why C++ sucks (2016 edition) by blub on Monday February 22, 2016 @07:52AM (#11150448)
With Boost Spirit you can write expressions akin to EBNF in your C++ code. The downsides are compile times (improved in the new version) and difficult to parse error messages at compile time.

If you stick to your code you should at least:

* add a copy constructor or delete it explicitly

* pass in the vector as unique_ptr to the constructor. This way the "takes ownership" will be clear without the need of a comment.

* add your missing includes e.g. vector

* stop using _ as variable prefix, it's forbidden

* throw from the constructor, don't exit

Boost variant + boost vector will allow you to eliminate all the manual memory management (boost vector allows incomplete types).

Re:Why C++ sucks (2016 edition) by loup-vaillant on Monday February 22, 2016 @08:44AM (#11150707)
Thanks for the tips, I'll apply them. Just a couple questions:

* Do you have a link about the _ (underscore) being forbidden? Our current coding rule make us use them right now.

* Is there a standard exception object I could throw? If I could just write something like `throw std::invalid_argument("what String");` that would be terrific. I don't want to construct a whole class just for that. (Maybe I have to, though?)

I'll also seriously consider boost. While it's a huge dependency, we are on Debian GNU/Linux, so it's probably not that bad.

Re:Why C++ sucks (2016 edition) by blub on Monday February 22, 2016 @08:56AM (#11150776)
You're welcome. The underscore thing is mentioned in 17.6.4.3.2 Global names, however it's more complex than what I said initially (this is C++ after all):

* double underscore or underscore + capital letter is reserved in any scope

* underscore is reserved in global scope

Your code is allowed in fact, sorry. My personal rule is that I never start an identifier with an underscore anywhere.

Re:Why C++ sucks (2016 edition) by blub on Monday February 22, 2016 @11:53AM (#11152210)
I missed the exc question: yes, invalid_argument is perfectly acceptable in my opinion. However, if you want to inherit from invalid_arg that is also possible - this would allow you to catch only this very specific type of error.
Re:Why C++ sucks (2016 edition) by gpderetta on Monday February 22, 2016 @05:32AM (#11149854)
You could consider using any of the already existing sum type libraries like boost::variant.

The code will certainly be more verbose than ML, but still better than roll-your-own.

Re:Why C++ sucks (2016 edition) by loup-vaillant on Monday February 22, 2016 @05:46AM (#11149914)
And manage another significant dependency. If boost::variant was as nice as ML, I would do it. But it's not. I'm not sure this is worth the trouble.
Re:Why C++ sucks (2016 edition) by gpderetta on Monday February 22, 2016 @05:59AM (#11149962)
If you are already using boost, as many projects are, it is no extra dependency. Otherwise there are many standalone implementations.

Egg.Variant is an high quality one: https://github.com/eggs-cpp/variant .

We are likely going to get a std variant type in the next standard, either as a library component or as a language feature.

Re:Why C++ sucks (2016 edition) by ksherlock on Monday February 22, 2016 @09:24AM (#11150930)
c++17 might include a variant template which would replace all that (or at least the backing storage for it). (std::variant<Value, std::string, std::vector<Expression *>>)
Re:Why C++ sucks (2016 edition) by Joky on Monday February 22, 2016 @06:43PM (#11155291)
So the C++ way is either to write a code generator for your own DSL, or to write a library that would allow to write you grammar in an eDSL fashion. No pain, no gain ;)
Re:Why C++ sucks (2016 edition) by masklinn on Monday February 22, 2016 @09:04AM (#11150817)
> Yes, I'm using Sum types, a feature that's pretty much unique to ML languages.

That's a bit too restrictive. Rust, Swift or Kotlin are not MLs.

Re:Why C++ sucks (2016 edition) by loup-vaillant on Monday February 22, 2016 @02:20PM (#11153485)
Good point. But we should let them age a bit. Right now they're a bit young for production code with deadlines and all. I hate C++, but I like the certainty that comes with tools I know.
Re:Why C++ sucks (2016 edition) by b169118 on Monday February 22, 2016 @05:19AM (#11149797)
Why do you need to use pointers for string and vector? Aren't they already heap allocated internally?
Re:Why C++ sucks (2016 edition) by loup-vaillant on Monday February 22, 2016 @05:42AM (#11149892)
My code compiles as is, so you can try yourself if you want.

If I didn't use pointers, I would have 2 errors. One would be about the use of an incomplete data type (Expression), and the other about trying to put something that doesn't have a "trivial constructor" in a union (String, Value, and std::vector<Expression>).

I can't use references either, because I would have to initialise them in the initialisation list of my constructor, which I can't do until I know the tag. I could still initialise the tag first, but that's specified by the order in which the data members are defined, rather than the order of the initialisation list —a rather dangerous idiom to rely on, should anyone modify the code.

Re:Why C++ sucks (2016 edition) by gpderetta on Monday February 22, 2016 @09:56AM (#11151139)
Note that in C++11 is perfectly fine to put a type with a non trivial constructor in an union.

You are right about the issue with std::vector and incomplete types. It will be possibly resolved in the next standard. In the meantime you can use something like boost::container::vector which explicitly support incomplete types.

Re:Why C++ sucks (2016 edition) by ksherlock on Monday February 22, 2016 @09:28AM (#11150960)
It's extra work, but you could use std::aligned_union<1, std::string, std::vector<Expression>, ...> to declare space for the union and then use placement new/manual destructor calls to initialize and destroy.
Re:Why C++ sucks (2016 edition) by hnbro on Monday February 22, 2016 @07:10PM (#11155417)
well, you would, you're in games. fairly substantial amount of stockholm syndrome in game programmers, imo. ;-)

bjarne and others in the community have talked about the heavy cost of legacy and compatibility many times. it's okay to like the language but acknowledge that it's not as awesome as it theoretically could be. it's okay to be unhappy with the warts and weirdness -- after all, such things are what the committee needs to be mindful of when progressing the language.

there's no real reason a language can't outright replace c++ without having many (most? all?) of it's idiosyncrasies. rust is a decent attempt, though the memory safety ideology seems too high friction to properly replace c++. there might be others who give it a shot someday.