About low-level programming...

I like C a lot. It took years to decide to devote time to learn it, because I had been told when I was young that it was a weird and difficult language. Now, I think it's elegant and straightforward.

But C++? Man... I can't help but feel it just wasn't very well thought out. Having classes and overloading is nice though...

Learn the standard template library (STL) and you'll fall in love with it. :slight_smile:

It lets you do linked lists, vectors, maps, etc. really elegantly. And it saves you having to re-invent a linked-list method every time you come up with a new structure.

Plus, it has a cough string class.

My needs often dictates how much I remember. I learned C++ several times but didn't retain everything or half what I learned. If you ask me what implicit copy constructor does in an exam, I'll tell you the right thing only because I looked it up a week ago. But friends, and templates? I don't really remember nor did I find use yet. Programming arduino limits the use of lots of features in C++ that I would have use programming a PC.

But friends, and templates? I don't really remember nor did I find use yet.

I can somewhat recommend this Free Online Class on "C++ for C programmers."
https://class.coursera.org/cplusplus4c-002

I mean, there are significant problems with this class. The prof talks too slow, and will spend 10 minutes explaining how "swap" works, only to have a HW assignment along the lines of "implement an AI that uses a generalized undirected graph datastructure with colored edge weights and Djiksta's algorithm to play the game of Hex." (did I say "along the lines of"? I meant "exactly." Grr.)
And apparently some of what he advocates is considered controversial (operator overloading?)

But on the other hand, he dives right into the things that are different than C and how and why they're useful. "templates" got talked about in the first set of lectures (thus the annoying diversion into the history of "swap".) Friends and inheritance and virtual functions are in there (whereas they tend to be either left as "advanced" topics or taken for granted in many books/classes that teach an OOP from the ground up.) IOsteams properly introduced as an operator-overloaded shift...

I'm flunking. But I'm getting a significant amount out of the class, and a lot of things have become much clearer to me...
I can live with that!

virtual static friend protected volatile templated function pointer,

I found that very funny, it is bar sport.
Having read subsequent posts im now thinking such a thing exists.
Gulp.

Well, every word is a C++ concept; I'm not quite sure whether they make sense all strung together.

OTOH, I've had to use tools to create/interpret C definitions for functions of stuff that returns (pointers to) arrays of function pointers, for real, and I'm pretty sure you can attach additional C++ concepts to those to make them even less intelligible...

I can understand function pointer and static friend. But what does it mean by virtual static friend then? If a function is static, can it be overridden by a class that inherits from the base class?

Where does volatile apply? The pointer is changing value so don't optimize code that accesses its value in a register or memory?

Templated is beyond my understanding. I don't use templates yet.

I did not try to make sense of it.
Function pointer was enough to put me off.

But how would you write plugin frameworks without function pointers? :slight_smile: They're the same as variable pointers, just referring to functions that can be called by address instead of values that can be read by address. Simple!

Templates? No idea. When I hear "template", I think of a stripped source file that can be customized to do something convenient without having to write it all from scratch. I assume the C++ concept is vaguely related, although not necessarily. "Overloading" sounds like something that would cause a compiler error, but it's actually a useful (if not sometimes obfuscating) feature, so who knows?

I'm a huge fan of clean, readable, intelligible code. Anything that makes code harder to comprehend is detrimental, although occasionally necessary. While I also like to write efficient code, if I have to pick between clarity and performance, it becomes an internal struggle weighted mostly by the number of times the given code will be run in a loop, or whether there will likely be events depending on its completion in the shortest possible time.

C++ just reeks of a language developed with all the latest theory and patterns, while being early enough that it didn't have the benefit of learning from the dubious attempts by many other well-established languages trying to achieve similar goals. (I could be way off -- I'm not a comp-sci history buff.) It's almost like you can see the parts where C++ departs from C syntax the same way you can tell when somebody added a room to a house 20 years after it was constructed. This side? Elegant, logical, well-planned and solid. This side? The contractor forgot to let the foundation settle, and the AC outlets all tap off the light switch in the adjacent bathroom, but the paint's fresh and vibrant!

Then there's PHP, which has absolutely no excuse. Sheesh. Is this perl or C? Nobody knows.

Templates are essentially a mechanism for making decisions at compile time that is much more powerful than preprocessor macros, and more HLL-aware than the usual assembler macros.
So you can do something like:

template <typename swappable_t> 
void swap(swappable_t *a, swappable_t *b)
{
   swappable_t temp;
   temp = *a;
   *b = *a;
   *b = temp;
}

And then if you have

int a, b;
student_t s1, s2;
  :
     swap(&a, &b);
     swap(&s1, &s2);

The first statement will cause a version of swap that works on ints to be compiled, and the second will cause a version of swap that works on students to be compiled.
I guess it can get a lot more complicated than that; templates are apparently a turing-complete programming language all by themselves. So they can do anything if you're willing to be obscure enough. (and thus, back to the sort of complaints in the original article!)

C is known to be dangerous, so most go in expecting trouble. If they don't find it? GREAT!!! But at least YOU WERE WARNED.

C++ was formed by a committee to make C safe. So poor blighters go in expecting a great experience and get devoured by beasts that never have been described. And if one survives, one has know way of knowing how one survived,it's as if all memories were erased.

I can understand function pointer and static friend. But what does it mean by virtual static friend then? If a function is static, can it be overridden by a class that inherits from the base class?

The first statement will cause a version of swap that works on ints to be compiled, and the second will cause a version of swap that works on students to be compiled.

POP! (That's a brain explosion)

---And if you think that's hard, try coding Android ADT (I couldn't get a FUDGING BUTTON to work.)

---And if you think the ADT is hard, try taking a state test. You need a PhD in Cryptology AND in Psychiatry to figure that out.

liudr:
I can understand function pointer and static friend. But what does it mean by virtual static friend then? If a function is static, can it be overridden by a class that inherits from the base class?

Where does volatile apply? The pointer is changing value so don't optimize code that accesses its value in a register or memory?

Templated is beyond my understanding. I don't use templates yet.

Hmmm, there are a few things not right, I wouldn't take that little quote as anything more than humor.

Static friend is redundant, static or friend should be used,
You cannot take pointers to template functions only a particular instantiation: foo<>, foo, which is not a template any more but a fully defined entity.
Virtual static is wrong, a static *non-*member is not bound to any object and therefore has no 'virtual' implications. This also applies to friend, these keywords imply a non-member entity.

POP! (That's a brain explosion)

What? In C, you'd have a swap function to swap two integers, so that (1, 2) would become (2,1):

void swap(int *a, int *b) {
  int temp;
  temp = *a;
  *a = *b;
   *b = temp;
}

But if you wanted to have a library of swap functions for different datatypes, you'd need to implement swap_int(), swap_long(), swap_float(), swap_string(), and so on. Plus, any data types that you defined yourself.

void swap_string(char **a, int **b) {
  char * temp;
  temp = *a;
  *a = *b;
   *b = temp;
}

C++ would make this somewhat easier, because you can have 'function overloading", where the same function name with different arguments results in separate code:

void swap(int *a, int *b) {
  int temp;
  temp = *a;
  *a = *b;
   *b = temp;
}
void swap(char **a, int **b) {
  char * temp;
  temp = *a;
  *a = *b;
   *b = temp;
}

(now, the top-level code can say "swap(a,b)" for several types of a and b.)
But - note that the actual CODE in those functions stays the same regardless of the types of arguments, except for the type specifications in the header and for "temp"; what you really want, so you can avoid rewriting the same code over and over, is to somehow pass that part of the function - the type - as an argument to some sort of macro. (I could almost imagine this as a C preprocessor macro, at least for an inline swap. But... Ugly!)

template <typename my_type> 
void swap(my_type *a, my_type *b)
{
   my_type temp;
   temp = *a;
   *b = *a;
   *b = temp;
}

This is what C++ templates give you. (one of the things they give you, anyway.) It's made more useful by also providing a "Standard Template Library" (STL) that provides a lot of common data structures and algorithms. So you can SORT your VECTOR of (user-defined) THING_TYPES without having to write any code for SORT, or VECTOR (a growable array-like thing) that is specific to THING_TYPE (other than a "compare-to" function.) (again, you can almost do this in C, given (dangerous) void* pointers, macros, and so on. But the C++ version is much prettier and less subject to being wrong.)

Oh.. that's kinda cool. :slight_smile:

I have to admit, I've been tempted to use a C++ compiler on my C programs just to take advantage of function overloading. That's one heckuva useful tool.

SirNickity:
I have to admit, I've been tempted to use a C++ compiler on my C programs just to take advantage of function overloading. That's one heckuva useful tool.

A slippery slope that may be, yesssss. Leads to the Dark Side, it does :wink:

If you really want to make your mind explode try to analyze template metaprogrammed code. After reading about template metaprogramming I wondered if I could achieve similar effects with the macro processor. Of course this is not the same but close Knight Rider Without Flicker | Blinkenlight :wink:

Templates are extremely useful, particularly if you get into the Standard Template Library (STL).

I admit it can be a little hard to get started, but once you do, your life is so much easier. Linked lists, maps, vectors, strings, all much much easier than writing yourself.

Here's a simple example. Say you have a structure of widgets, and you want to have any number of them in a linked list:

#include <iterator>
#include <list>
#include <pnew.cpp>

typedef struct
  {
  int foo;
  char bar;
  byte fubar [10];
  }  widget;  

std::list<widget *> myList;
  
void setup ()
{
  widget * w;
  
  w = new widget;
  myList.push_back (w);
  w = new widget;
  myList.push_back (w);  
}  // end of setup

void loop () {}

Done. You can add to the front or the back of the list. You can traverse the list forwards or backwards. If you find a particular item you can delete it from the middle, front or back. You don't need to muck around with "next" or "previous" pointers, like you would if you do it manually.

You have other container types like maps (for key/value pairs), vectors (where you want to go straight to item 42), and so on. Queues and stacks are variants on vectors, however there is a deque type (double-ended queue) which is more efficient for those applications.

There are various utilities in the library, for example you can sort containers, or do things like delete every entry matching a certain condition.

Containers can be pointers (as in the example above) or actual data (not pointers) provided they can be copied and assigned.

Below is a similar example, however this time we use widget directly (not a pointer to widget):

#include <iterator>
#include <list>
#include <pnew.cpp>

typedef struct
  {
  int foo;
  char bar;
  byte fubar [10];
  }  widget;  

std::list<widget> myList;
  
void setup ()
{
  widget w;
  
  myList.push_back (w);
  myList.push_back (w);
    
}  // end of setup

void loop () {}

I wrote some of my own libraries (a reinvented wheel no doubt) to handle lists and ring buffers and that sort of thing. Easy enough, but yeah, not having to do it at all is easier. Not to mention the maintenance is done for you, and everyone knows how it works just by seeing the initialization.

Key/value pairs are one thing I miss when writing C after working in scripting and web development languages. I love hashes. Very handy for indexing and validity checks ($sanitized = $valid_terms[$input]) etc. Inefficient as all heck, I'm sure...