|
I spent over an hour tracking down a compile issue in my C++ code yesterday because I forgot to mark a derivation as virtual.
C++ can be finicky but between it and C they really are the only languages that can fulfill the promise of "code once, run anywhere" despite requiring a recompile to do so.
For a long time, I was hoping .NET would at least become as ubiquitous as Java, and it slowly has (almost).
But my devices have gotten smaller, my needs of my language more demanding, and garbage collection will always hamstring these higher level "device independent" languages in terms of where they can operate.
I do love C#, but it just won't run on what I code for these days. C++ is my first love anyway. template just owns all, and where it doesn't, the preprocessor steps in. It's gorgeous. I can convince the compiler to do just about anything. Me being a fan of domain specific languages and coding, C++ also is the only major language with a flexible enough compiler and preprocessor to make that a reality.
I started my JSON pull parser in C#
I ported it to compile with the Arduino SDK/toolchain
Then I ported it to compile with C++ in general (without being Arduino specific)
Now it runs in places my C# pull parser never will, and that's deeply satisfying.
Besides, money for me today is in C++ code. I just don't like business development, and C++ keeps bizdev contracts out of my hair. Nobody wants to pay for a backend or frontend implementation of a web based site or otherwise business application in C++. Good.
This is almost a dear john letter to C#
Also I'm kinda falling in love with VS Code
Real programmers use butterflies
modified 13-Dec-20 7:05am.
|
|
|
|
|
La Strega wrote: I forgot to mark a derivation as virtual. It's now recommended that only the original function be virtual and that derivations only be override or final . So I guess you're using a version of C++ that doesn't have those tags yet.
C++ can be finicky but between it and C they really are the only languages that can fulfill the promise of "code once, run anywhere" despite requiring a recompile to do so. That's damning with faint praise given that you have to develop or find portable libraries that start with sockets and go all the way up the food chain. But the STL does have <thread> , which is good for building toy systems!
C++ keeps bizdev contracts out of my hair. I can see the appeal, but if you have that library that goes all the way down to sockets, you might not escape so easily!
This is almost a dear john letter to C# I was going to suggest jill, but that would be hypercorrection.
|
|
|
|
|
Greg Utas wrote: It's now recommended that only the original function be virtual and that derivations only be override or final . So I guess you're using a version of C++ that doesn't have those tags yet.
I'm doing that. I'm talking about the inheritance list, like
class B : virtual public A {};
Like that
Greg Utas wrote: That's damning with faint praise given that you have to develop or find portable libraries that start with sockets and go all the way up the food chain.
That's true but the same is the case w/ embedded gadgets generally i've found. ecosystems gotta ecosystem.
Greg Utas wrote: I can see the appeal, but if you have that library that goes all the way down to sockets, you might not escape so easily!
I'll try to avoid it.
ETA: Congratulations on what I am assuming was a 2nd prize win for last month.
Real programmers use butterflies
|
|
|
|
|
class B : virtual public A {}; I'd forgotten about this use of virtual because I don't use multiple inheritance. You're naughty!
Congratulations on what I am assuming was a 2nd prize win for last month. The rewrite article[^] was a co-winner. I've noticed that they give out 2 firsts and 2 seconds for these contests.
|
|
|
|
|
What's so bad about multiple inheritance? It's one of the things I love about C++.
Say I have a class that manages a cursor over a streaming input and a capture buffer for reading data into.
Say I want to separate capture buffer storage concerns from input device concerns.
So I make a LexContext derivative for keeping a fixed length buffer (StaticLexContext<S>) and one for reading from a FILE* - FileLexContext. Then I can just do
template<const size_t S> class StaticFileLexContext :public FileLexContext, public StaticLexContext<S> {
StaticFileLexContext() {
}
};
and Bob's your uncle.
If you refuse to use multiple inheritance, you will either need to duplicate code, or create a third "helper/utility" class or module to keep the shared implementation. =(
Real programmers use butterflies
|
|
|
|
|
It was more of a troll because of the religious debates. I'd lean toward the recommendation to only multiply inherit from classes that themselves derive from an abstract class. Without the abstract classes, admixed classes tend to make assumptions about each other, so refactoring is needed to make other combinations work later. And sometimes there is no "later".
|
|
|
|
|
Greg Utas wrote: Without the abstract classes, admixed classes tend to make assumptions about each other, so refactoring is needed to make other combinations work later.
That's a good point.
I tend to think of this scenario as intermixing class and interface, but I still conceptually treat my two groups of virtual functions in the base (to be filled by two separate derived classes typically) as two "interfaces" even though they don't have an abstract base to back them. The abstract base is mixed in to the base class itself.
I can see avoiding that for complicated classes or classes that will be worked on by multiple people, and classes that will likely be added to a lot, because it quickly becomes a source of confusion as well as a maintenance hole.
However, for a lot of really simple composable legolike core classes I find this technique to be unobtrusive (not requiring a ton of type definitions) and relatively maintainable.
It's a "good enough" approach (IMO) when you don't need full on separate interfaces/contracts, and you want to keep implementation somewhat together. It quickly breaks down for complicated things though so it's basically a shortcut for simple cases.
Real programmers use butterflies
|
|
|
|
|
In the early days of Atmel devices C++ was very clumsy and not many people used it, they used C mostly. I kind of led a crusade for C++ and thank heavens in the last couple of years it has become very mature.
Disclaimer; I was in no way responsible of its maturity, just thankful for it.
I'm not sure how many cookies it makes to be happy, but so far it's not 27.
JaxCoder.com
|
|
|
|
|
Yeah, you kind of need C++11 at least or it's not that grown up. I really like a lot of the features they are adding to the language this century and I'm excited about C++20. With C# other than yield/async/await/var all the other additions have been pretty useless and marginally annoying to me.
Real programmers use butterflies
|
|
|
|
|
Yeah 11 was a great update and like you im anxious to see 20 hit the streets.
I've been tied up remodeling our house for 4 months now and it will probably be a couple more before I can get back to any kind of tinkering. Don't even have my computer here and have a brand new CNC machine assembled on my work bench at the old townhouse that I've not even had a chance to use. I've got a ton of projects lined up and raren' to get to it.
I'm not sure how many cookies it makes to be happy, but so far it's not 27.
JaxCoder.com
|
|
|
|
|
I really like 17 - solely because inline static initialization is a very nice addition.
"They have a consciousness, they have a life, they have a soul! Damn you! Let the rabbits wear glasses! Save our brothers! Can I get an amen?"
|
|
|
|
|
Good old binary compilation. You can get the latest features in your code by switching to a newer compiler without waiting for the latest "framework"/virtual machine to be deployed everywhere. I mean, well the stdlib and STL stuff notwithstanding.
Real programmers use butterflies
|
|
|
|
|
Part of the clumsiness might have been Embedded C++: no exceptions, no templates, no RTTI. The rationale was a concern over code bloat, but they should have taken the whole language and let individual development teams manage any bloat.
|
|
|
|
|
I agree with that regarding templates. But with structured exception handling you have potentially OS level interop you may have to do depending if your "OS"/CPU supports it or is "exception aware" and that can be architecture dependent. Also, I can't imagine even trying to do SEH on my little 8bit ATmega2560. I can see there being barriers to implementing an SEH mechanism depending on platform and depending on how it is implemented, but maybe I'm wrong.
I've never actually used RTTI, so I wouldn't miss it.
Templates only bloat your code depending on how you use them. It's fine - even desirable to use them on embedded because things like fixed length buffers usually require some sort of max value tied to a block of memory somewhere that was fixed size at compile time. I do that very thing with templates on a lot of my classes for the arduino.
template<const size_t S> class StringBuilder { ... }; like that, where S is the size of your fixed buffer.
Real programmers use butterflies
|
|
|
|
|
I wouldn't miss RTTI either.
True C++ exceptions shouldn't be a problem. But a platform that didn't support POSIX signals would be degenerate for nasty exceptions, so you'd have to design accordingly. Even the full C++ standard says that those are basically undefined behavior.
|
|
|
|
|
Yeah. I'm not really holding the lack of SEH support on embedded against anyone, is my point. Maybe it could be done on some, but it's probably hit or miss if it will even work "properly"
I love C++ and even if I can use some of it over plain old C i'll take it. C++ is a beautiful language, in whole or part.
It's truly my favorite. I missed it during my C# sabbatical but I forgot how much I loved it until I came back to it.
Also VS Code makes working with C++ in linux a joy. Kudos to Microsoft.
Real programmers use butterflies
|
|
|
|
|
One can hope that herbceptions will help there, but proposed treatment for out-of-memory errors is a bit questionable.
|
|
|
|
|
Out of memory will always be a problem without a separate stack, as in sigaltstack .
These guys are still clueless. The standard should mandate the ability to turn a POSIX signal into an exception in a signal handler. Not all platforms could support it, but so what. This also says something about the inane fetish for noexcept .
I would write a proposal but have better ways to spend time than debating pedants in the C++ standards community.
|
|
|
|
|
I traded my Ferrari for a golf cart because the Ferrari couldn't carry my gold clubs.
It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it.
― Confucian Analects: Rules of Confucius about his food
|
|
|
|
|
And OP's analogy is "I traded my golf cart for a Ferrari because I didn't need to carry golf clubs."
|
|
|
|
|
I'm cosigning this.
Real programmers use butterflies
|
|
|
|
|
You'll be sorry when our loan is called!
|
|
|
|
|
Not the way I would look at it but to each their own.
Real programmers use butterflies
|
|
|
|
|
|