Allegro.cc - Online Community

Allegro.cc Forums » Off-Topic Ordeals » 15+ years after learning C/C++, I finally learned what a typedef is for

This thread is locked; no one can reply to it. rss feed Print
 1   2 
15+ years after learning C/C++, I finally learned what a typedef is for
bamccaig
Member #7,536
July 2006
avatar

What is it about C++ vectors that are "an ugly mess"? I've never had troubles with them.

It's been a while, but I think one of the "gotchas" that bites a lot of people is that internally copies to objects are somewhat common within the STL containers, even when you don't necessarily intend for it to happen. When a copy gets destroyed, it might invalidate the pointers of all other copies unless an explicit copy constructor is defined to make proper copies of pointers. Meaning, if you define a destructor to clean up heap memory, then you better make sure you also define a copy constructor that reallocates new memory for each copy so that internal copies don't invalidate the object. That's based a bit on ancient threads here, and a drunk's memory. I don't think it has ever bitten me personally, and I'm not sure about the semantics. But yeah, in general, C++ has lots of subtle semantics like that that can bite you in the ass. The saying goes, the more experienced you are with C++ the less you know (because you become aware of the too many gotchas to remember).

relpatseht
Member #5,034
September 2004
avatar

I don't know. The more C++ things I see, the more I feel like the primary function is to make it easy to poorly design systems. The nice thing about really poor memory management is it highly discourages random tiny heap allocations, which are about the slowest thing you can do and a hallmark of poor design. C++ makes it easy to waste resources while hiding costs. Eh...

I'd take C with templates any day. RAII, classes, and inheritance just make it easy to write slow code.

Neil Roy
Member #2,229
April 2002
avatar

Then why not use assembler?

Actually, I have looked into assembly language. Many decades ago I used to code in assembly on my old C64 and I absolutely loved it. I looked into Windows assembly and it looks pretty good as well.

The thing is, C is as close as you can get to assembly without coding in assembly. Actually, you can include assembly code within C. I used to do it all the time back in the DOS days and loved it.

As for memory management, I have never had a problem with it in C. I love pointers, I am not afraid of them like most C++ programmers seem to be. When I allocate memory, I immediately write code to free it up again. It's just never been a problem.

When I need something similar to vectors, I wrote my own functions to do it. It's not rocket science, it was fairly easy to code and I enjoyed doing it.

C++ has it's own issues which have caused people to stop using the constructors and destructors and switch to unique pointers which have to be the ugliest things I can imagine. If you can remember to use them and how, than why can't you remember to simply write code to free the memory by hand in C?!

I see C++ to be a solution to a problem that just doesn't come up.

But hey, that's all just my opinion. If you like it and feel more comfortable using it, have at it, but DO NOT act like I am not staying current because I prefer to code in C or I will chew your fucking head off.

---
“I love you too.” - last words of Wanda Roy

Polybios
Member #12,293
October 2010

I've used pure C for many years before starting with C++. If you get over the stage that you have to use every language feature just because you can, it can save you lots of time.
Also, if you know what you are doing with your memory (a skill which some programmers coming from Java or other languages with more automated memory management seem to lack), nothing stops you to use higher level features wisely.

The using syntax is very nice indeed.

Chris Katko
Member #1,881
January 2002
avatar

Neil Roy said:

C++ has it's own issues which have caused people to stop using the constructors and destructors and switch to unique pointers which have to be the ugliest things I can imagine. If you can remember to use them and how, than why can't you remember to simply write code to free the memory by hand in C?!

C++ is a walking design-by-committee. Don't let it scar you for better languages.

-----sig:
“Programs should be written for people to read, and only incidentally for machines to execute.” - Structure and Interpretation of Computer Programs
"Political Correctness is fascism disguised as manners" --George Carlin

Kitty Cat
Member #2,815
October 2002
avatar

Neil Roy said:

If you can remember to use them and how, than why can't you remember to simply write code to free the memory by hand in C?!

It would be so much better if people never made mistakes.

But there is something to be said about expediency and reasoning potential. Simply
std::unique_ptr<Type> obj(new Type());
And it's all taken care of by the compiler and STL. Don't need to go looking through the code to see everywhere it can return, ensuring you have free/delete calls prior to each one. Nor do you have to worry about remembering if/when another return path is added, or if you move the allocation to a different place that may move it before or after preexisting return paths.

It also makes ownership semantics clear. If I do:

std::unique_ptr<Type> obj(new Type());
...
some_function(obj.get());
obj.reset();
...
return;

both me and the compiler know some_function is just being given a reference/pointer to the object, but the caller retains ownership and the object is still valid afterward for the reset call to delete it. The compiler knows what's going on, and it's obvious to the reader (presuming they know C++). By comparison in C:

Type *obj = CreateType(); // Can return NULL? An aliased pointer?
...
some_function(obj); // Who's responsible for the object now?? Do we still own it,
                    // or did the function take ownership?? Is it still a valid
                    // object??
DeleteType(obj); // Use after free??? Double-free???
obj = NULL;
...
DeleteType(obj); // Valid with a null pointer????
return;

While the person who writes this code may know what's going on, someone else coming into the project later may not. They'll just have to work on assumptions that this is correct, and hope no one breaks those assumptions. Further, the compiler has less information to work with about what the code's doing, and has less opportunity to warn you about funny business with the pointer, or to optimize. The compiler doesn't know what some_function or DeleteType do, nor does it know what DeleteType does with a NULL pointer, so it has to make that second call even though it should be a no-op (or could be a crash waiting to happen, but can't warn you about it).

By comparison, in C++ the compiler intrinsically knows what new and delete are. It knows that new will return a valid non-aliased pointer to a fully constructed object, and when the object was deleted and the pointer cleared to null in the reset method, the destruction at the end of the block becomes a safe no-op and doesn't need to call anything a second time.

--
"Do not meddle in the affairs of cats, for they are subtle and will pee on your computer." -- Bruce Graham

Gassa
Member #5,298
December 2004
avatar

alias this=data; //<--- treat all uses of a superfloat as if it was superfloat.data
//(and if that fails, then try superfloat.whatever() as opposed to superfloat.data.whatever())

Actually, it's the other way around: first, try it with the new super_float struct, and if that fails, try it with the original thing, data.
Makes more sense this way.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

typedef is very useful, especially with templates.

#SelectExpand
1typedef std::map<std::string , Object*> OBJMAP; 2typedef OBJMAP::iterator OMIT; 3 4OBJMAP objmap; 5OMIT it = objmap.begin(); 6while (it != objmap.end()) { 7 collide_left(it); 8 ++it; 9} 10auto collide_left = [] (OMIT omit) { 11 Object* o = omit->second; 12 if (o->X() < 0) {o->VX *= -1;} 13}; 14 15std::for_each(objmap.begin() ; objmap.end() ; collide_left);

I dare you to do that in C using as many or less lines. You would have to implement sort, binary search, iterators, and for loops. And then try making it work on polymorphic objects. You can't do it as easily in C as you can in C++. There's no denying that C++ makes development faster. And then once you wrap your head around that, you need to realize that C++ development is still as slow as molasses compared to some other languages today. Not that C++ performance is slow, just development time.

Samuel Henderson
Member #3,757
August 2003
avatar

Funny enough, my wife (who is studying computer programming at our local college) just had a lab assigned on using typedef.

I don't recall learning anything about using typedef when I took the same course over a decade ago ... but it could just be that I wasn't paying attention at the time because I already knew about it and how it worked.

bamccaig may be able to correct me on this?

=================================================
Paul whoknows: Why is this thread still open?
Onewing: Because it is a pthread: a thread for me to pee on.

bamccaig
Member #7,536
July 2006
avatar

I don't think typedef was specifically covered in our college program, but then our class was likely held back because there were a lot of whiners in it. :-/ Most of which dropped out by second year, but a few managed to pass the program with a near 4.0. Go figure... ::)

In reality, I learned most of my C++ knowledge from A.cc after I graduated. I barely understood C++ in college because I don't think it was explained very clearly, but that was also probably partially because the class kept getting interrupted by people that couldn't comprehend the most basic things and so I think some of the material was rushed in the end.. I thought I had a good handle on it until I tried to figure out more complex ideas and couldn't. And then participating on the boards here, asking questions, I discovered how little I knew and learned a lot more.

But OO in C++ just doesn't work as intuitively as you'd like it to. Part of that is because the language gives you full control, but that comes at the cost of having to understand more details and semantics and bloating the language with extra semantics. The fact that polymorphism only works through pointers is kind of silly. Hell, the compiler would automatically get the address of an object to get a pointer, or all objects could intrinsically have a pointer to metadata object containing type information and vtable and such... All of which comes at a cost so I'm sure the 80s and 90s crowd would throw a fit.

In the end, I think that C++ has a lot of design flaws, but that's largely because it was designed when there wasn't really an equivalent available yet so it was blazing a new trail... There's always mistakes made with anything done for the "first" time. Hell, there's usually still mistakes on the 2nd and 3rd iteration and so on... Also, the hardware was much more limited at the time so I'm sure the design decisions made more sense 30 years ago..

Chris Katko
Member #1,881
January 2002
avatar

I feel like C++ is trying to be two languages and sucks at both.

A "compatible" language going back to the 70's/80's. DON'T. FIX. ANYTHING. BAD.

A "new" language with "new" features (that D has had literally for a decade, ;D ).

Then again, they don't add new features that are actually useful (or take literally 20 years to finally get around to doing it). MODULES?! MODULES?!?!?!? I think in c++17 they FINALLY added number separators (D has it!) so you can do 1_000_000. Meanwhile, Motorola C had it in ... the 90's, I know, I used it.

I actually saw a good video from expert/master-of-C++ Scott Meyers on why C++ is so terrible at the high-level decision making process.

video

(Only a few reasons because he's using them as an example to D devs, "don't be like this."--he says he's got tons more examples.) This is a great video to watch on C++ if you've got an hour to chill out.

I'm trying to remember one point he made though. He was saying that "everything in C++ has a reason." Why is this thing strange? Because of X interferes with Y. Everything has a reason... but... while every committee member has "their thing" and "their reasons" for it. IIRC, he's saying it suffers because there is no cohesive vision between all of them / everyone is afraid of breaking or changing anything. (See 43:00)

He also talks about (37:00) at Essential vs Accidental complexity. Essential is, the program has complexity. Accidental is, the language (or API, or whatever) sucks so you have to remember extra complexity where it's not needed.

"The only thing I have experience with that is more complicated than C++, is the US tax code. And to be fair, it had a couple hundred years to get complex." -- Scott Meyers

Quote:

std::unique_ptr<Type> obj(new Type());

That looks like keyboard vomit to me. I mean, I get it, but typing "std::unique_ptr<Type>" is a ridiculous amount of typing to get something so fundamentally essential to using the language. That should be a SINGLE LETTER, or some other kind of small-number-of-symbols quick alias.

I know what you want, you know what you want, so why do you have to type out a string with angle brackets, colons, and underscores just to get there. And a real-world example would be even longer!

I mean look at this:

//(From a random github search)
std::unique_ptr<std::string> s(new std::string("hehe"));
std::vector<std::unique_ptr<std::string> > v;
v.push_back(std::move(s));

Every year... C++ becomes a little more like LISP.

{"name":"lisp_cycles.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/e\/5\/e5b5612aa6ec954a824d349b4f020d45.png","w":640,"h":211,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/e\/5\/e5b5612aa6ec954a824d349b4f020d45"}lisp_cycles.png

Now contrast that with my a made up language:

^string s = "hehe";
^string[] v;
v ~= s.move;

//^ = unique pointer (<-made up)
// string is standard language feature (ala D)
// ^string[] is an array of strings (ala D) with unique ptrs 
// .move is move semantics. Probably could do even smaller with a character if needed often enough. 
// ~= is add element to array (ala D)

But you see how the "core" of what we're talking about doesn't need to be keyboard vomit? And the "what's going on" is fairly clear, even to someone who doesn't know the language? I didn't need to explain to you how, or why I choose language features. With a couple of comments, you knew all you needed to read my code and could read MORE code using the same constructs, without further comments to explain them.

To be clear, I'm not talking to "you" as if you're the owner of C++, or some huge proponent of it.

-----sig:
“Programs should be written for people to read, and only incidentally for machines to execute.” - Structure and Interpretation of Computer Programs
"Political Correctness is fascism disguised as manners" --George Carlin

Kitty Cat
Member #2,815
October 2002
avatar

Quote:
//(From a random github search)
std::unique_ptr<std::string> s(new std::string("hehe"));
std::vector<std::unique_ptr<std::string> > v;
v.push_back(std::move(s));

Simplified:

std::vector<std::unique_ptr<std::string>> v;
v.emplace_back(std::make_unique<std::string>("hehe"));

This can of course be simplified further by making aliases to avoiding the recurring std:: and <type> syntax, if you use them often.

But you see how the "core" of what we're talking about doesn't need to be keyboard vomit? And the "what's going on" is fairly clear, even to someone who doesn't know the language?

I couldn't have told you what ^string or v ~= s.move; meant if you didn't explain it. To me, ^ is XOR (as a bitwise operator) or pow (for simple mathematical expressions), and ~= comes across to me as "roughly equal". My C/C++ background also makes me see s.move as accessing the move member of s, rather than executing a move from s into v. So that made up language of yours would be near meaningless drivel to me, like someone trying too hard to make a compact language while forgoing readability and clarity.

I'm not saying C++ is perfect, it is certainly over-expressive, but it's not like other languages don't have their share of issues, if they even hit the same use-case that C++ does.

--
"Do not meddle in the affairs of cats, for they are subtle and will pee on your computer." -- Bruce Graham

bamccaig
Member #7,536
July 2006
avatar

I know what you want, you know what you want, so why do you have to type out a string with angle brackets, colons, and underscores just to get there.

On a side note, I realize that most C-derived languages use - as a subtraction operator and the lack of any other kind of universal structure makes it impossible to use for other purposes, but note that - is much easier to type than _.

In Lisp, because "functions" / "operators" always come first within a Lisp form (i.e., set of parenthesis) and arguments are separated only by white-space, it doesn't need to worry about operators willy-nilly and so names are free to use hyphens and pretty much any character that isn't a handful of special characters (off the top of my head: white-space, parenthesis, single-quote since that is a special quote operator, double-quote since that starts a string, perhaps semi-colon cause that starts a comment in some dialects, and probably many more I'm forgetting, but generally fewer than most languages).

This can save a bunch of time typing code because it saves your hand the stretch of holding shift while you type the - key (at least on US and many related keyboards). If you haven't explored too far away from C this idea might be very foreign to you, but until you explore it you might not realize how freeing it is.

As another aside, most command shell languages also support a hyphen/dash within a command or argument name, and if you spend any time using one you've probably seen this countless times. Keep that in mind if you are ever developing a command line interface, which I hope you are if you ever develop software that interacts with users because it's the easiest to write and maintain (you can always build a GUI on the command-line or better yet a shared library central to both, but can't do the reverse). When you name your commands or subcommands/options/switches, never use an underscore unless that is somehow meaningful within the context. You can type the dash/hyphen easier, and it reads better too.

Quote:

But you see how the "core" of what we're talking about doesn't need to be keyboard vomit?

One programmer's vomit is the next programmer's elegance. Of course, I generally prize terseness, but the consequence of true terseness is usually complexity and many more magical symbols.

As an example, Perl can be very terse, and people are even more afraid of it than they are of C, despite it being a much higher-level family of languages. To contrast that, Python syntax is generally quite simple, and it has taken the world by storm as a result. Some code snippets are inevitably longer in Python, but there's less "line noise" which makes it an easier read for most. In the last decade, it appears that the world has chosen a winner as Perl is losing its user-base and Python has taken off in popularity.

Kitty Cat said:

So that made up language of yours would be near meaningless drivel to me, like someone trying too hard to make a compact language while forgoing readability and clarity.

I have to agree. While I understand the point Chris was trying to make, I think that the chosen syntax wasn't given enough thought to really accomplish the intended goals. Of course, I'm sure it was a contrived example, or maybe based on some language I'm not familiar with, such as D. But it just reenforces that "elegance" is more difficult to dream up in code than you might think. And syntax choices are usually a struggle between several competing goals (e.g., terseness and clarity, simplicity and expressiveness, familiarity and trailblazing).

Lisp is arguably very elegant and pure, and yet, most people cannot wrap their heads around it. It requires an "aha" moment that many people never achieve. It's very ancient history has also lead to several competing tribes which fragments the members that do get it and ultimately sabotages its ability to gain any traction from new members. And yet, many of the best programming concepts originated in a Lisp dialect, and many popular, modern languages still lack most of them.

Nevermind what the machine is doing under the surface. Give the human an elegant way to tell the machine what to do, and let the machine figure out the best way to do it to optimize its resources. In a perfect world, we wouldn't need a "unique_ptr<T>" at all. In a perfect world, the memory is not managed by man, but by machine, and it's done well enough to outperform any optimizations a man could hope to achieve. In a perfect world, the machine can translate a high-level program into a perfectly optimized low-level program. That's the ultimate utopia. Of course, true fantasy land is where the "program" is literally just a human speaking to a machine. Mind you, as dreamy as that concept it, it also leaves us somewhat out of a job (unless we go back to school to learn the extremely complex task of building such machines).

Chris Katko
Member #1,881
January 2002
avatar

I bet I could come up with better examples if I tried. I literally github'd the first result of using std::vector.

Hey guys, let's use a 3-D array using proper C++!:

std::vector<std::vector<std::vector<double>>> Array3D(X, std::vector<std::vector<double>>(Y, std::vector<double>(Z)));

What. The. Flying. Fuck.

Want a dynamic 3-D array in D?

float [][][] suck_it; //And yes, it also supports sparse arrays

Want a static 3-D array in D?

float [15][15][15] down; //Just PUT NUMBERS IN IT.

If you can't tell the difference in quality of intent and readability between those two, you need your head examined. The top one can't be explained with "it's just a 3-D array" because of the Accidental complexity of C++ is so far off the chart you have to explain STL, namespaces, why you have to (EMBED (variables (inside( eachother))) like some insane reverse polish notation, when we're all taught and immediately understand that data[x][y] is a 2-D lookup. You have to explain constructors and why you have to feed one into the next. The list (ha! pun!) just keeps going on.

When one of the greatest C++ programmers around says, "The only thing more complex than my language I get paid to do talks on, is the tax code", that should not be something you throwaway without merit. That's how you become an old fart that can't be bothered to listen to anyone or progress forward. In otherwords, a C++ programmer in 2018. Per that very same talk, "Nobody in C++ user community, or committee says anymore, 'The most C++ code has yet to be written'. I haven't heard that in years, and that says something about the mentality of the language."

Back to code, and D code can be tweaked to be as fast as the fastest C++, and even faster in some benchmarks than the sometimes atrocious STL that hides allocations like a a ferret does keys.

bench.b test:

Language	Time, s	Memory, MiB
Kotlin	1.78	28.4
C++ Gcc	1.94	1.0
Rust	2.16	4.8
Nim Gcc	2.50	0.6
D Gdc	2.61	1.4
D Ldc	2.85	1.0
...
Python	314.79	4.9
Python3	412.13	5.5

Json Test:

Language	Time, s	Memory, MiB
D Gdc Fast	0.35	234.1
Rust Pull	0.51	207.7
Rust Struct	0.53	226.2
C++ Rapid SAX	0.72	1.0
C++ Gason	0.83	582.2
C++ Rapid	0.94	243.6

https://github.com/kostya/benchmarks

So I'm not demanding (or even asking) you to join the D community. Do whatever you want, I really don't care. But what you won't do, is pretend that:

std::vector<std::vector<std::vector<double>>> Array3D(X, std::vector<std::vector<double>>(Y, std::vector<double>(Z)));

is easier to read, write, debug, and be productive with, than this:

double[][][] Array3D;

I don't have to surgically replace my little finger from pressing SHIFT every 2 characters on my little netbook just to write some bloody code that CREATES an array! We haven't even talked about using iterators across a 3-D array. Now you've got to explain how iterators work.

If C++ wasn't bad, Boost wouldn't exist to try and fix it.

  // Create a 3D array that is 3 x 4 x 2
  typedef boost::multi_array<double, 3> array_type;
  typedef array_type::index index;
  array_type A(boost::extents[3][4][2]);

  // Assign values to the elements
  int values = 0;
  for(index i = 0; i != 3; ++i) 
    for(index j = 0; j != 4; ++j)
      for(index k = 0; k != 2; ++k)
        A[i][j][k] = values++;

Those poor bastards trying to abuse insane C++ template magic (which is worth an entire talk on how bad they are in C++ and ONLY in C++) to get something "resembling" easy-to-use C++ code. And yet, still not as simple as D... which can compile down to straight-C.

  double A[3][3][3]; // vs   typedef boost::multi_array<double, 3> array_type;
  foreach(i ,2d; A) //foreach 2d strip in 3d array A
  foreach(j, 1d; 2d) //foreach 1d strip in 2d strip
  foreach(k, element; 1d) //foreach element in 1d strip
    {
    A[i][j][k] = values++;
    }

And in D there are easier ways to do that too that involve functional programming. But we're talking emitting the same code while I didn't have to make my fingers bleed, or even spend time writing it. It took me more time to read the C++ code and write comments than write the code.

And again, I'm not saying D is "the best". It has tons of flaws. The point is, C++ programmers have become the new COBOL/FORTRAN/etc programmers that think "I learned programming when it was hard, so EVERYONE SHOULD SUFFER LIKE I HAVE and do on a regular basis."

Programming should be easy. The TASKS YOU SOLVE are the ones that are supposed to be hard. Not the damn tools used to fix them. (Fun fact: The video also covers that. Tool complexity VS Task complexity.)

-----sig:
“Programs should be written for people to read, and only incidentally for machines to execute.” - Structure and Interpretation of Computer Programs
"Political Correctness is fascism disguised as manners" --George Carlin

bamccaig
Member #7,536
July 2006
avatar

Of course, D has its own problems. I won't pretend to be up-to-date on them, but I think it was something like different forks for a standard library, and other such issues that make it more difficult to use. It's not like "D" is a united concept where everybody is doing the same thing with it. It's more like different, tiny groups are pulling in different directions, and the technology is in pieces unable to come together into a real C or C++ killer. The ideas are sound, but the technology is not production quality from what I've heard. That's a real killer for a programming technology. Until that changes, no matter what theoretical advantages D has over C or C++, it'll remain nonviable for most projects and programmers. Years ago I learned some of the very basics, like how strings are (or were?) just basically array types, but the array types could do all the string-y things for all element types. That's great.. But where is this technology today? Why aren't the big, free software loving companies using it? How can we unite all the groups interested in D to work toward a common goal and common future? How can we make D software compatible with C projects and visa-versa? I remember thinking how cool D would be, but having trouble even getting an environment setup that could compile D. And even if I got one setup, Google was just saying there are competing camps so it's just headache after headache. There are less painful high-level languages. Maybe not as fast, but probably the time you'll save in writing and maintaining software and development environments is the time you'll lose at run-time so it all probably balances out. :P

Append:

The C++ standard library has been embarrassing for decades and I don't think modern standards have gone far enough to improve upon them. Of course, there are alternatives. While people hate on Boost for template-runtime bloat, it is at least a stable library with very high-quality solutions to many problems. C++ the language supports a common, if "non-standard" solution to common problems, but the community hasn't done a very good job of coming up with a single "wheel" to solve common problems. It's probably fair to blame Microsoft for part of that. With free software hackers on one side and proprietary, IDE loving, broken compiler hugging, materialists on the other, there seems to be no common ground. The only time they come together and compromise for the better is when the materialists are dragged forcefully towards free software with perfectly groomed nails. Fortunately, that has been happening quite a bit for the latter part of the decade, but for C and C++ it's way too late.

Chris Katko
Member #1,881
January 2002
avatar

You gotta let me stop edit'whoring before replying! =D I mention that D has plenty of problems and isn't the "only" or "Better" solution. It's that there ARE SOLUTIONS and ignoring them is not the high ground, but just denial.

Programming languages have gotten better. C++ has not (except at a snails pace.)

We still, after what, 20 years of requests, have no ABI binary compatibility mode even though C++ legend Herb Stutter even wrote a proposal for it... in 2014.

https://isocpp.org/blog/2014/05/n4028

What's he know, all he did was write "the books" people always tell you to buy when you ask "how do I become an advanced/expert C++ programmer."

Exceptional C++ (Addison-Wesley, 2000, ISBN 0-201-61562-2)
More Exceptional C++ (Addison-Wesley, 2002, ISBN 0-201-70434-X)
Exceptional C++ Style (Addison-Wesley, 2005, ISBN 0-201-76042-8)
C++ Coding Standards (together with Andrei Alexandrescu, Addison-Wesley, 2005, ISBN 0-321-11358-6)

Now, I like D. D's policy is mostly "does it make sense in the scope of the entire language?", yes? Then they add it. They had static ifs, someone said "Why not static foreach?" everyone was like "Oh shit, that's a good point." So they just added it. D is still moving too slowly, but that's still great. (Also has problems like them re-using the 'static' keyword to mean practically every possible thing on the planet. You really can't comprehend how bad it is!)

But people are working on Nim, Python, Go, and on Rust. And a myriad of other languages. I prefer D so far, because it's "C++ without the bull shit." That is, focused on productivity. And the code snippet I've shown with arrays shows that. D saves my fingers. D is about making the best use of the little time I have, and accomplishes the same as C++ code, but with a fraction of the lines of code. (Another point the video makes). Other languages do to.

So again, my point is, there are better languages out there that are worth your time to try.

With huge advances in computing power, even "Scripting" languages like Lua, and Python have become viable for many applications they weren't before.

Although, I heard a great point for what a systems language is. A platform, where there is no "upper bound" on speed. If you can crank out 5% more speed, you're saying millions of dollars. So the guy in the video got called in to help them replace an entire architecture that used virtual functions (dynamic dispatch), with templates (static dispatch). That tiny difference between having and not having a couple pointer jumps was worth calling in a C++ LEGEND and paying his huge fees, just to optimize it. D is a language that can compete in that realm. Python cannot. Which is fine, Python isn't TRYING to be a systems language. But it's certainly a point in the favor of D that it can still target the areas were C and C++ systems target: Where the finished product has to be as close to perfect assembly as possible, but you still want to remain productive and easy to catch bugs. That's the C/C++/D niche.

Meanwhile, contrast that with Python2/3 in those benchmarks being 200x to 300x slower. That's... not really that bad. It's two orders-of-a-magnitude. If something takes .005 seconds in D, or 1 second in Python, and you run it once (parse a word list), are you going to care? Some cases, yes. Like when that becomes 24 hours instead of 5 minutes. But often times, writing bad code (algorithm complexity of n^3 or n^4) is a bigger problem than the language itself! And many video games that don't run 1000's or 10000's of objects ever frame can get by in Lua or Python and they exist on Steam and make money. And those languages are ALL ABOUT coder productivity. John Romero uses Corona SDK. A complete 2-D game library/engine that uses Lua, and he even has a game with it on Steam. That let him focus on designing his game, and not the code. I prefer more code control, but yeah. Lua is a first class choice for making games now. (And has been for a long time, but this is ALL. CORE. GAME MECHANICS CODE. done with Lua. Not just AI thinking in Age of Empires while the C++ binary calculates pathfinding).

So I'm not really making a related point there, but an observation of how great it is to have options. And that learning them has really opened my mind of what coding could be.

I keep meaning to write a video to explain what I consider "the next era of programming". Herb Stutter is working on adding metaclasses to c++ for example. Even if you're a C++ hermit, we're now talking about C++, so if you're great at C++, why don't you already know what metaclasses are??? ;) Because they're new!

[edit] Done edit whoring! [/edit]

bamccaig said:

While people hate on Boost for template-runtime bloat, it is at least a stable library with very high-quality solutions to many problems.

I think the issue is that they're (ab)using templates, which are language constructs, to solve problems with the language itself. They're trying to fix C++... from inside C++! Which is why the templates are SO HUGE and compiling is SO SLOW and the error messages are SO COMPLEX.

Could you imagine trying to use a regex, to "Create" a new kind of regex? You wouldn't even try. It doesn't make sense.

Or how about using C macros to add object oriented programming to C. You could try! It'd be a fun exercise. But nobody would dare consider this productive:

CONSTRUCTOR(StdFile, (const char*nam,const char*acc))
CONSTRUCT (File,()); 
this->hdl = fopen(nam,acc);
assert (this->hdl );
END_CONSTRUCTOR

METHOD(StdFile,Read,(void*buf,int n),int)
if (fread(buf,n,1,this->hdl) < 1)
    return -1;
return n;
END_METHOD

http://www.drdobbs.com/extending-c-for-object-oriented-programm/184402731

Fun trivia: Is this C, or ALGOL60? ;)

They tried to solve the a fundamental language problem of C (for their use-case), by using C, and then writing code from inside C to try and become C++, and made it even worse than C++. Instead of trying to add useful features to C by abusing macros, use C++. Instead of trying to make C++ a good language by abusing templates, use D. (or whatever)

Again, it's a really cool experiment to understand how inheritance and OOP work by implementing it in C. C is a GREAT middleground between thoughts, and assembly! But if I saw someone do that in production code, we'd have a talk, and then a code review.

And remember guys, this is all coming from the guy who literally programming NOTHING BUT C++ for over a decade because C++ was "the best choice." Well, then I tried Python and C# and I was blown away by my productivity gain. But I wanted speed too, so I ended up with D. And I'm not going to stop there. I'm going to learn LISP and Haskell to open my mind further. And never stop opening my mind.

Quote:

, but I think it was something like different forks for a standard library,

That's long over. It was Phobos vs T...tow...atog....tomoato...whatever it was. It's gone. It's just Phobos is the standard library. Now D (D2 technically) is all open source, and there are two language designers. Everyone else submits proposals (actually the designers also submit proposals). But again, use whatever. Just don't think that "C++ has everything". It's slow, ugly, and missing features that people are using right now to be more productive, and make complex problems easier to comprehend.

I'd be glad to enumerate all the flaws I've seen in D, but that's not really the argument here and now, as I'm not even advocating D, just that there are other options and they are worth learning.

-----sig:
“Programs should be written for people to read, and only incidentally for machines to execute.” - Structure and Interpretation of Computer Programs
"Political Correctness is fascism disguised as manners" --George Carlin

Neil Roy
Member #2,229
April 2002
avatar

I'll stick to C. And I rarely use macros. I do love some of the insane examples people come up with to make a language look bad. Examples most people never use, well, except that C++ vector<> example, I see that all the time. I will see std:: out the ying yang and if it is code I want to try out, I will add "using namespace std;" at the top and POOF, half the code can vanish! Or my personal favourite...

std::cout << "hello world" << std::endl;

Instead of using something like

std::cout << "hello world\n";

Or using namespace std you can remove the std:: and really make life easier and easier to understand.

I really get a kick out of online tutorials I have followed (on 3D programming, not C++) which will often create a string object to store a char* to a simple string that OpenGL wants... and OpenGL will want a char*, so they end up passing myStringObj.c_str() etc... which is really ridiculous.

One guy wrote a game engine in C++ and instead of using the constructor and destructor, created an init() function and another one to deallocate. When I tried out his code I eliminated a lot of wasted space by rewriting it to use the constructor/destructor. And I don't even like C++, but sheesh people, if you're going to use it, use it properly at least! In the guy's main() he created the game object, followed by myGame.init() which made me ;D as that could have been avoided by putting all the init() code into the constructor which is called automatically.

I don't know, I can do what I want in C. I see a lot of far out examples, but my games are written 100% in C, compiled with a C compiler, not a C++ one using the latest version of C (2011, though I rarely use many of the modern features), most of my code can get along with C99, which to me, is the first REAL version of C which corrected some issues and I felt finally polished the language. But that's just my personal opinion.

If you like C++, great, use it, if you like D, awesome, use it. I like C, don't treat me like I am stuck in the past or some stupid shit like that. It's fast, efficient and does what I like. I don't tend to use macros or typedefs for anything except my structs, so my code is straight forward, you know what I am doing.

As for OOP in C, why? I can't stand OOP and I noticed online that even some seasoned C++ developers are moving away from OOP. They still use C++, just not classes so much, which I have thought about doing. Using C++ for certain aspects like vectors that are nice and otherwise coding in much the way I do C now. Though I do enjoy the challenge of recreating C++ features I like in C; which means I will never be challenged to create a C style OOP as I can't stand it! So no problem! If I liked OOP, I would use C++, be stupid to stick to C and create macros and junk to emulate OOP and classes when C++ has it already.

And I have coded in C++, I just prefer C. In my Text Maze 3D project I made up, it was written in C++, and visual studio, two things I rarely use. I just didn't use classes. Strings and vectors mostly for that one. Nothing I couldn't have done in C, but it was a spur of the moment thing so I wasn't worried about it.

---
“I love you too.” - last words of Wanda Roy

Gassa
Member #5,298
December 2004
avatar

C++:  std::vector<std::vector<std::vector<double>>> Array3D(X, std::vector<std::vector<double>>(Y, std::vector<double>(Z)));

D:    float [][][] suck_it; //And yes, it also supports sparse arrays

To nitpick again, these are not equivalent. The D line translates to just the half of that,

C++:  std::vector<std::vector<std::vector<float> > > v;

And if you want to specify sizes in D, it's linear instead of quadratic but still longer:

D:    auto v = new float [] [] [] (X, Y, Z);

Trickier yet another bit when you want a non-default initializer for each element. Still linear in the number of dimensions though.

-----

Also, perhaps people now have a non-quadratic syntax for multidimensional vector declaration in C++17: any C++17 expert around? Or will have in C++20. Or in C++23. And there will perhaps even be a convenience function to split a std::string into a std::vector of std::string tokens by C++29, and finally a std::bigint by C++35... well, you get the point.

C++ does evolve, and if you have to use it, you perhaps welcome every new standard with joy. But it's hard to evolve at a competitive pace when you have to maintain, what, 40? years of backwards compatibility.

Kitty Cat
Member #2,815
October 2002
avatar

Hey guys, let's use a 3-D array using proper C++ [stackoverflow.com]!:

std::vector<std::vector<std::vector<double>>> Array3D(X, std::vector<std::vector<double>>(Y, std::vector<double>(Z)));

What. The. Flying. Fuck.

If you need a fully dynamic 3D array like that, you should probably rethink your design. Or you're going to need it so rarely, what does it matter if you have to write something like that once in a blue moon? It's a pretty good deterrent, actually. Or if you do actually need to use them so regularly, you're probably better off with a higher level language where performance and memory use aren't a concern.

Quote:

Want a dynamic 3-D array in D?

float [][][] suck_it; //And yes, it also supports sparse arrays

Want a static 3-D array in D?

float [15][15][15] down; //Just PUT NUMBERS IN IT.

That small of a change completely changes the underlying behavior of the array? Between being a flat local allocation, vs 3D fragmented heap allocations with triple memory indirection and behind the scenes memory management. Or is it always 3D fragmented heap allocations with triple memory indirection and behind the scenes memory management, and the numbers just prevent it from growing or shrinking?

Besides, empty array brackets on a declaration already means something in C and C++.

Quote:

If C++ wasn't bad, Boost wouldn't exist to try and fix it.

Boost exists in its current form because the C++ committee misunderstood the versioning procedure with ISO, and thought they had to wait longer to make a new C++ version. Boost gained as much prominence as it did from that mistake, because it took so long for the C++ standard to update with new features and C++ coders came to rely on Boost for new features. These days Boost is less important for general C++ coders because C++ has been integrating the more useful features and has been updating more rapidly, and it's more useful as a staging ground to hammer out new or complicated ideas, see what can work and what's actually useful, or for things that don't really belong in the C++ standard.

--
"Do not meddle in the affairs of cats, for they are subtle and will pee on your computer." -- Bruce Graham

Chris Katko
Member #1,881
January 2002
avatar

Wow this is a great talk on metaclasses.

{"name":"2P8y7nX.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/8\/8\/88dbb229d9f27cba4716f3e52be34b5a.png","w":1074,"h":563,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/8\/8\/88dbb229d9f27cba4716f3e52be34b5a"}2P8y7nX.png
Left is C++ (text vomit, what if you forget to make one function pure virtual? !@$! you, that's what.), right is an example proposal of an interface syntax that better languages than C already have.

...Then he FLIPS THE SCRIPT and tells you, he's not proposing interfaces. He's proposing a syntax to LITERALLY WRITE YOUR OWN FEATURES for C++.

{"name":"CGkHfPJ.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/3\/a\/3a652a53dfe24706d905d82d9ee0941b.png","w":964,"h":513,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/3\/a\/3a652a53dfe24706d905d82d9ee0941b"}CGkHfPJ.png

video

I'm already sold. Sign me up. This is a tool toward what I've been talking about for years. Not writing "code", writing "code guidelines" that the compiler statically enforces.

-----sig:
“Programs should be written for people to read, and only incidentally for machines to execute.” - Structure and Interpretation of Computer Programs
"Political Correctness is fascism disguised as manners" --George Carlin

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

I made a recursive template for Multi Dimensional Arrays in C++ a while back. I programmed iterators for it and everything. So it was as easy as :

typedef MultiDimArray<3 , double> D3D;// don't try this at home kids;

D3D d3d;
d3d.Resize(depth , height , width , 0.0);
d3d[z][y][x] = 1.0;
D3D::iterator it = d3d.begin();
int i = 0;
while (it != d3d.end()) {
   printf("Value #%d is %5.2lf\n" , i , *it);
   ++i;
   ++it;
}

I made reverse and const iterators too. It was fun.

But really, multi dimensional arrays are super easy. The hard part is lookup. When you've only got 2 or 3 dimensions, it's not super bad, but more is hard.

Just for fun I was messing around with this again, and I came up with something horrible with templates, but then I managed to come up with this. This is about as good as it gets with C++ and Multi Dimensional Arrays :

#SelectExpand
1 2template <class O> 3class NDA { 4protected : 5 struct DIM { 6 int i; 7 int sz; 8 DIM() : i(0) , sz(0) {} 9 }; 10 DIM* dimen; 11 12 int ndim; 13 O* oarray; 14 15 int dim_index; 16 17public : 18/// Index(O** object_array , int* dimensions , int ndimensions); 19 NDA(int ndimensions , int* dimensions , O** object_array = 0) : 20 dimen(0), 21 ndim(0), 22 oarray(0), 23 dim_index(0) 24 { 25 Allocate(ndimensions , dimensions , object_array); 26 } 27 void Allocate(int ndimensions , int* dimensions , O** object_array = 0) { 28 Free(); 29 dimen = new DIM[ndim = ndimensions]; 30 for (int i = 0 ; i < ndim ; ++i) { 31 dimen[i].sz = dimensions[i]; 32 } 33 oarray = new O[Volume()]; 34 if (object_array) { 35 *object_array = oarray; 36 } 37 dim_index = 0; 38 } 39 ~NDA() { 40 Free(); 41 } 42 void ResetIndices() { 43 for (int dim = 0 ; dim < ndim ; ++dim) { 44 dimen[dim].i = 0; 45 } 46 } 47 int Size(int dindex) { 48 return dimen[dindex % ndim].sz; 49 } 50 int Size() {return Size(0);} 51 int Volume(int dindex) { 52 if (dindex < 0) {return 0;} 53 if (dindex >= ndim) {return 1;} 54 return dimen[dindex].sz*Volume(dindex + 1); 55 } 56 int Volume() {return Volume(0);} 57 void Free() { 58 if (dimen) { 59 delete [] dimen; 60 dimen = 0; 61 } 62 if (oarray) { 63 delete [] oarray; 64 oarray = 0; 65 } 66 } 67 O* PTR() { 68 return &oarray[GetFullIndex()]; 69 } 70 int GetThisIndex(int dindex) { 71 return dimen[dindex%ndim].i; 72 } 73 int GetFullIndex() { 74 int total = 0; 75 for (int dim = 0 ; dim < ndim ; ++dim) { 76 total += GetThisIndex(dim)*Volume(dim + 1); 77 } 78 return total; 79 } 80 NDA& operator[](int n) { 81 if (dim_index == 0) { 82 ResetIndices(); 83 } 84 DIM* d = &dimen[dim_index]; 85 if (n >= d->sz) { 86 n %= d->sz; 87 } 88 d->i = n; 89 ++dim_index; 90 if (dim_index >= ndim) { 91 dim_index = 0; 92 } 93 return *this; 94 } 95 96};

And then it's use is super simple :

#SelectExpand
1 2class Object { 3public : 4 int x; 5 float y; 6 double z; 7}; 8 9 10 11#include <cstdio> 12 13 14 15int main(int argc , char** argv) { 16 17 (void)argc; 18 (void)argv; 19 20 const int NDIM = 3; 21 int dim[NDIM] = {3,4,5}; 22 NDA<Object> i3d(NDIM , &dim[0]); 23 24 for (int z = 0 ; z < i3d.Size(0) ; ++z) { 25 for (int y = 0 ; y < i3d.Size(1) ; ++y) { 26 for (int x = 0 ; x < i3d.Size(2) ; ++x) { 27 Object* o = i3d[z][y][x].PTR(); 28 o->x = x; 29 o->y = y; 30 o->z = z; 31 } 32 } 33 } 34 35 Object* o = i3d[2][3][4].PTR(); 36 37 printf("XYZ = %d , %f , %lf\n" , o->x , o->y , o->z); 38 39 return 0; 40}

And if I really wanted to make it fancy I could make iterators for it. But it supports multi dimensional array syntax NDA[z][y][x] gives you an NDA& and then you just call the PTR() function to get a pointer to the array at that point. Takes care of allocation and deallocation for you as well.

 1   2 


Go to: