💾 Archived View for tozip.chickenkiller.com › 2022-08-05-cpp.gmi captured on 2023-06-16 at 16:08:43. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2023-03-20)
-=-=-=-=-=-=-
Created 2022-08-05
I've upgraded to gcc v12, which has the C++ standard in it, although it's not fully compliant. Too bad it doesn't have "format()", for example. There's some nice stuff in C++20, and I've barely scraped the surface of what it can do. It is clear that some people have a deep understanding of C++. Perhaps I'd consider myself a journeyman in C++. I no longer work in industry, but I guess I'm around average in terms of knowledge. I think most programmers are well below mastery level, mostly banging out code that works. And that suffices. Google and Facebook are not going to be knocking on my door any day, although curiously some time ago I did have someone *claiming* to be from Google say they were interested in interviewing me. I didn't take them up on their offer. I'm not interested in joining the Cult Of Google, and I'm confident that they wouldn't have me as a member, either. But I digress ...
I have been knocking together some polymorphic classes in C++. What I wanted to do was create a class called Io, which has mostly abstract functions, but some concrete functions, too. I then have derived classes which I use for io on the console or via sockets. It was quite frustrating to get going. The messages can be a bit cryptic sometimes, and it's difficult to know what exactly it is the compiler doesn't like. In some cases it seems that I have mixed up what can or maybe can't be done in the base vs derived class. Another case I came across is that I hadn't properly implemented a virtual function in the derived class. The compiler didn't make that obvious what the problem was, though.
The good news is that I've got something working, and it seems to work correctly. I have yet to implement "<<" properly. The C++ library seems to implement it for io by actually returning a function that is called, takes a stream, and returns a stream. Something like that, anyway. It's how "endl" works. You might ask how endl manages to output a newline char to the stream and flush it, given that it's a variable and not a function. Well, the answer appears to be that it returns a pointer to a function that does this. "<<" then executes this function. So that's how it works."<<" is a so-called "fluent" interface, i.e. it takes a stream and returns a stream, so that you can chain several such operator together. So I should do something similar to my own Io class. I have currently run out of chickens to sacrifice to get it to work just at the moment. I'm waiting for a goat to arrive in the post.
But yeah, polymorphism seems to be quite good in C++, and seems flexible enough to do much of what I want. What'd be really nice to see in C++ is the Haskell equivalent of typeclasses. Then we could define recursive data structures that is needed for tree representations.
I'm using polymorphism for a BBS (Bulletin Board System) that I'm putting together. It's useful to be able to test stuff out on the command line as well as via telnet. For that I need to be able to plug in different I/O systems polymorphically. I did take a brief look at Boosts ASIO recently, but figured that what I already had was good enough. It looks quite powerful, with a learning curve to match.
An alternative approach that springs to mind is to, perhaps, try to decouple model logic from I/O via coroutines. It's a sparkly new feature in C++17. "Meh, could be easier" is my conclusion so far. If I want to use coroutines, I'm inclined to try rolling my own. It should be compatible with C, too, although probably not as robust.
You need to decide if you want your coroutine to have multiple instances. If not, you can simply make everything static. If you do, then you need a struct that holds all the state, and is perhaps more prone to error. But, meh, is it really all that much more difficult than whatever the hell it is that that C++ implements? Plus, you get to actually understand what it is you've done. I've seen a neat implementation of "defer()" by gingerBill (creator of Odin programming language), and I think I might be able to adapt it to generate labels on the fly. These labels can be used in computed gotos, so that you can reinstate the coroutine. In the past I have defined my own labels explicitly, but this might hide some of the implementation a bit better.
My BBS actually "does something", but is not available online. It has a natty little gopher client built in. My BBS is not without its rough edges, but I might decide to publish-and-be-dammed in the near future. A real bonus of gopher/spartan/gemini is that it fits the way I want to create content. It's simple and quick. It does what it needs to do, then stops. I want my BBS to have a different feel to it, though. It should be more interactive, dynamic and arty. There should be a game-like feel to it.
Anyhoo, that's all I've got for you today. Have fun.