Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411486 Posts in 69371 Topics- by 58427 Members - Latest Member: shelton786

April 24, 2024, 08:50:40 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)What modern features you want to see in C++?
Pages: 1 2 [3] 4
Print
Author Topic: What modern features you want to see in C++?  (Read 6227 times)
fluffrabbit
Guest
« Reply #40 on: October 15, 2019, 07:04:59 AM »

It's safe to assume that whoever calls MakeThing() owns Thing and therefore must FreeThing(). You've got to do this yourself with graphics APIs, so a language managing client-side memory is really just a nice thing to do; how considerate of it.

Pi sounds like a nice feature. But is Pi defined by the standard? cppreference lists the mathematical symbol, but it's an irrational number and FPU internals can vary. Is there a standard x86 float32 Pi, x86 float64 Pi, etc?

Might be nice if I could do something like assert( pi == acos(-1) ).
« Last Edit: October 15, 2019, 07:10:14 AM by fluffrabbit » Logged
qMopey
Level 6
*


View Profile WWW
« Reply #41 on: October 15, 2019, 08:23:20 AM »

Just about nothing C++ does cannot be done manually with C. But the keyword here is manually.

That's not necessarily a bad thing.
Logged
Schrompf
Level 9
****

C++ professional, game dev sparetime


View Profile WWW
« Reply #42 on: October 15, 2019, 10:15:36 PM »

But it is.
Logged

Snake World, multiplayer worm eats stuff and grows DevLog
Daid
Level 3
***



View Profile
« Reply #43 on: October 15, 2019, 10:57:05 PM »

Just about nothing C++ does cannot be done manually with C. But the keyword here is manually.
That's not necessarily a bad thing.
In a small amount of cases, it is good to have the manual option. In many, it just takes longer, introduces more bugs, and is harder to refactor.


Simple example, you have a string heavy code base. Lots of string processing is happening. In "Do it yourself" code, you'll have a lot of "char*" and friends, manually keeping track of ownership. In "Automated" code, you have a custom string class that contains a pointer to the string buffer, allocating and freeing memory and move symantics. (ignoring the fact that you could have used std::string)

Now, performance of both will be about the same. The "char*" will most likely be slightly faster, as the code needs to do slightly less checks in some cases. I mean, the optimizer is good, but not perfect.

But, now you learn about something called "short string optimization". Simply put, if you manage strings like this:
Code:
struct String
{
  char* buffer;
  size_t length;
  size_t capacity;
}
Then this structure is 24 bytes (assuming 64bit). But, if we do this:
Code:
struct String
{
  char* buffer;
  union {
    struct {
      size_t length;
      size_t capacity;
      bool flag;
    } remote;
    struct {
      char[16] buffer;
      bool flag;
    }
  }
}
Then we can place short strings inside the data structure. Which sounds silly, as it needs a bit more instructions to work. However, it's quite a speedup, as you have less cache misses. And, it's now 32bytes, which is generally exactly a cache line.

For the "automated" code, you just update your class, and all is well. For the "Do it yourself", you'll spend insane amount of time updating your codebase.


std::string does this optimization as of gcc 5, and visual studio does it as well (not sure when it was introduced). And it makes a lot of sense. But if you always do everything manually, you would never have this improvement.

Quote
Pi sounds like a nice feature. But is Pi defined by the standard? cppreference lists the mathematical symbol, but it's an irrational number and FPU internals can vary. Is there a standard x86 float32 Pi, x86 float64 Pi, etc?
It's a bit hard to read from the page, but the c++20 standard defines pi_v as a template. And thus pi_v<double> is the double, pi_v<float> is the 32bit floating point. And pi_v<long double> is, whatever your compiler decides that a long double is (which could be the same a double)
« Last Edit: October 16, 2019, 12:40:04 AM by Daid » Logged

Software engineer by trade. Game development by hobby.
The Tribute Of Legends Devlog Co-op zelda.
EmptyEpsilon Free Co-op multiplayer spaceship simulator
fluffrabbit
Guest
« Reply #44 on: October 15, 2019, 11:01:05 PM »

I salute you for bothering with cache optimizations. Maybe one day I will care about such things.
Logged
Daid
Level 3
***



View Profile
« Reply #45 on: October 16, 2019, 12:22:52 AM »

I salute you for bothering with cache optimizations. Maybe one day I will care about such things.
Actually, my point is. I don't have to. I got it for free from smarter people then myself. Beer!


I generally do not optimize for cache usage, as my usually work environment does not have data cache. I'm generally more concerned with interrupt latencies, DMA usage and clock drift.
Logged

Software engineer by trade. Game development by hobby.
The Tribute Of Legends Devlog Co-op zelda.
EmptyEpsilon Free Co-op multiplayer spaceship simulator
Daid
Level 3
***



View Profile
« Reply #46 on: October 16, 2019, 12:29:02 AM »

Just about nothing C++ does cannot be done manually with C. But the keyword here is manually.
That's not necessarily a bad thing.
But answer me this. When is it a good thing?
Logged

Software engineer by trade. Game development by hobby.
The Tribute Of Legends Devlog Co-op zelda.
EmptyEpsilon Free Co-op multiplayer spaceship simulator
fluffrabbit
Guest
« Reply #47 on: October 16, 2019, 01:15:29 AM »

Just about nothing C++ does cannot be done manually with C. But the keyword here is manually.
That's not necessarily a bad thing.
But answer me this. When is it a good thing?
I can answer that. Garbage collectors and reference counting have overhead. Calling free() instead gives you top speed when using dynamic heap memory. When I converted a neural network library from STL to plain old C, it nearly doubled in speed.

Of course, you could feel the same way about that as I do about short string optimization. Get low when you gotta, but most of the time the speed probably isn't necessary. It's those few times when there is a frustrating bottleneck somewhere that things get optimized. And no, the STL does not automatically optimize all the time. C is generally faster in my experience.
Logged
Schrompf
Level 9
****

C++ professional, game dev sparetime


View Profile WWW
« Reply #48 on: October 16, 2019, 01:19:55 AM »

Ignorance posed as a virtue. Grats.

Now back to the topic: What modern features you want to see in C++?
Logged

Snake World, multiplayer worm eats stuff and grows DevLog
Daid
Level 3
***



View Profile
« Reply #49 on: October 16, 2019, 01:38:42 AM »

Ignorance posed as a virtue. Grats.
Indeed. The speed boost going from C++ to C most likely had nothing to do with C++ vs C, but more with using the STL in wrong ways.
For example, std::shared_ptr has quite a bit of overhead, as it has threading guarantees. And that's the only class I can imagine that you have if you talk about reference counting and garbage collection. But that has nothing to do with C vs C++. See how box2d does efficient memory management and still is C++.


Now back to the topic: What modern features you want to see in C++?
A decent easy to use socket library, that does ipv4 and ipv6 in a sane manner. But knowing the standard comity, they most likely make a horrible convoluted mess, or forget something simple essential as getting your local addresses. The posix C interface is no fun to do ipv4 and ipv6 properly in.

Something as simple as connecting to a dns name is convoluted by the fact that you can get ipv4 and ipv6 addresses from the name resolv, but you might have ipv6 support but not being able to connect with ipv6. So you need to loop until you find one that works.
So you end up with something like this:
https://github.com/daid/SeriousProton2/blob/master/src/io/network/tcpSocket.cpp#L158
IF you accept that "::connect()" is blocking, if you want a non-blocking "::connect()", well, that is possible, but good luck keeping track of all the state.

And then with upd, there is the mess of broadcasting, unicasting and multiple network interfaces. And windows messing up by not having the proper default broadcast interface setup (it happily broadcasts by default to a virtualbox virtual network interface)
Logged

Software engineer by trade. Game development by hobby.
The Tribute Of Legends Devlog Co-op zelda.
EmptyEpsilon Free Co-op multiplayer spaceship simulator
Schrompf
Level 9
****

C++ professional, game dev sparetime


View Profile WWW
« Reply #50 on: October 16, 2019, 01:46:16 AM »

The speed boost going from C++ to C most likely had nothing to do with C++ vs C, but more with using the STL in wrong ways.
I'm not even arguing what's faster and where. I'm fed up by "This one is faster in C, and I want that." and "This one is faster in C++, but nobody needs it anyways.". Or the same with "easier". Or "shorter". Whatever you put in, you can find an example of in this very thread. That's true ignorance.

I personally want to get rid of headers and the whole include stuff. Haven't tried modules, though. Maybe it's not as bad as some random people told me on the Internet.
Logged

Snake World, multiplayer worm eats stuff and grows DevLog
fluffrabbit
Guest
« Reply #51 on: October 16, 2019, 02:36:38 AM »

I don't have to listen to you assholes, but I feel that I should point out there is obvious personal bias and I don't like C++ as a language. I still use it, and I can't tell you anything you don't already know about it, but my reasons for hating it are just as valid as any other preference.
Logged
Daid
Level 3
***



View Profile
« Reply #52 on: October 16, 2019, 03:21:15 AM »

I personally want to get rid of headers and the whole include stuff. Haven't tried modules, though. Maybe it's not as bad as some random people told me on the Internet.
I think it will take 10 years before we see a serious uptake of modules. I do think the concept is good, but it requires:
  • Major changes in the source code that define the module
  • A compiler that understands modules
I'm currently stuck with C++14, and 1 compiler that halfway supports C++11. So compiler adoption is always slow (I mean, the speed at which systems adopt new compilers. Not the speed at which compilers adopt the new features. Which is amazing fast for gcc, msvc and clang)

But the change in the packages themselves to be modules is where the problems start. Why make something a module that works for 60% of the users if a classic header+library works for 100% of the users?

And then there is macros, which, as far as I understood, are not supported in modules. Love them, hate them. But there are things that are impossible or very verbose without macros.



I would also love if we could add in the standard that <windows.h> is not allowed as a header file. That thing is a monster, a dragon, an abomination... it defines so much random stuff in the global namespace, and microsoft does not seem to do any attempt in cleaning that up.
Logged

Software engineer by trade. Game development by hobby.
The Tribute Of Legends Devlog Co-op zelda.
EmptyEpsilon Free Co-op multiplayer spaceship simulator
fluffrabbit
Guest
« Reply #53 on: October 16, 2019, 05:25:01 AM »

Okay, I want std::hash_list now. It's like everything from std::vector plus everything from std::unordered_map, so you get efficient table lookups with a guaranteed order of elements. Address by either number or string, which magically deduces either vector-style or map-style addressing, just like a JavaScript object.
Logged
Daid
Level 3
***



View Profile
« Reply #54 on: October 16, 2019, 05:44:23 AM »

You mean flat_map? Like boost has?
Logged

Software engineer by trade. Game development by hobby.
The Tribute Of Legends Devlog Co-op zelda.
EmptyEpsilon Free Co-op multiplayer spaceship simulator
fluffrabbit
Guest
« Reply #55 on: October 16, 2019, 05:53:56 AM »

Yeah, I guess. I'm drafting an extension to std::vector which I'm calling a "mesa". The familiar syntax of std::vector with some of the functionality of a hash table. Either one works, but for now the weird old standard stuff is still standard.
Logged
powly
Level 4
****



View Profile WWW
« Reply #56 on: October 16, 2019, 06:09:51 AM »

Reflection would be kinda cool. I’d also like a change from template metaprogramming to sensible constexpr programming; less thinking about how the language is compiled and in what order are things considered, more just stating ”for these types do this, for these do this other thing, else default to this”.

edit: btw, this
But answer me this. When is it [doing stuff manually] a good thing?
I can answer that. Garbage collectors and reference counting have overhead. [...]
felt like a weird argument -- no garbage collection or reference counting was suggested. RAII for releasing memory (for example with a std::unique_ptr) is the direct "non-manual" counterpart for new/delete (so for simple types, malloc/free). It has no run-time overhead, at least if you don't move the ownership around -- for most cases it compiles to the same exact thing as the manual counterpart. It's not completely free in all cases and introduces compile-time overhead and makes the language one step more complex, but in this case I'd say the benefits outweigh the downsides.
« Last Edit: October 16, 2019, 06:47:18 AM by powly » Logged
qMopey
Level 6
*


View Profile WWW
« Reply #57 on: October 16, 2019, 09:37:21 AM »

Simple example, you have a string heavy code base. Lots of string processing is happening. In "Do it yourself" code, you'll have a lot of "char*" and friends, manually keeping track of ownership.

Well, actually no that's not at all the case. Typically there is a string abstraction, for example, string ids and a string interning table. And I do agree with your point that using char* everywhere like the wild west would be inferior to a more modern C++ string approach. However, I do still strongly feel the aforementioned intern strategy could be superior in most all cases, and could introduce an interesting discussion for us here.

In my experience the short string optimization isn't a very good one compared to the intern table I mentioned before. Instead of a 32-byte (or however large) "short string optimization", you just have a 64-bit id as the "short" representation. Even smaller, and much simpler.

The real crux you seem to have against the more "manual" style I am proposing, is you don't want to do menial bit-twiddling work involved with lifetime management. Which I completely understand. In some scenarios just using std::string and not worrying about these details is perfectly fine. However, in other cases having the knowledge and ability to apply a more tailored approach is also very valuable.

My opinion is the other approach (the id + intern table) will be more portable, and thus more resilient and robust during long-term code maturation.

Actually, my point is. I don't have to. I got it for free from smarter people then myself.

This is another fundamental difference between myself and the C++-zealots, so thank you for bringing it up. In my experience the people designing and implementing C++ are, yes, smart, but horribly unwise. Sure, they are intelligent, but they don't make good choices and their designs do not solve problems effectively. Sure, you might disagree, but my main argument against your disagreements would be that you simply glean a lot of value from the the widespread familiarity everyone has with all these "official" C++ features. And I totally agree - since most everyone that knows C++ is familiar with all these features it becomes extremely valuable when working as a team. Everyone can hold the same assumptions about the code, and communicate more about the problem-at-hand rather than fundamental computer science or language details.

However, the reason I disagree is that I personally view the downsides of these C++/RAII styles as so detrimental, that they produce a strong net negative in the long-term, despite all the great benefits of widespread familiarity canonical and modern C++ brings to the table.

Just about nothing C++ does cannot be done manually with C. But the keyword here is manually.
That's not necessarily a bad thing.
But answer me this. When is it a good thing?

The couple of points below you will probably find interesting.

felt like a weird argument -- no garbage collection or reference counting was suggested. RAII for releasing memory (for example with a std::unique_ptr) is the direct "non-manual" counterpart for new/delete (so for simple types, malloc/free). It has no run-time overhead, at least if you don't move the ownership around -- for most cases it compiles to the same exact thing as the manual counterpart. It's not completely free in all cases and introduces compile-time overhead and makes the language one step more complex, but in this case I'd say the benefits outweigh the downsides.

Usually RAII is talked about in the context of smart pointers. In this case you're dealing with reference counting, and in effect, garbage collection. And yes, there is a performance hit. You hit the reference counted variable underneath, which will can cause false-sharing across cores in a multi-threaded scenario. This is just one example. Another example is the unpredictable nature of freeing up cycles of smart pointers referencing one another -- you can get huge lag spikes in the middle of performance critical operations due to a large blob of smart pointers all referencing each other, only to finally fall out of scope from the single base smart pointer holding the blob to the rest of the main process. It does not compile to the manual counterpart at all, at least in my experience.

But besides the objectively negative performance hits, I personally think there are other downsides that are way worse than the simple performance hits. In my experience if a developer is forced to inline their lifetime calls explicitly a couple interesting things happen.

1. It becomes possible to reason about the nature of lifetimes. How many of these things exist at any given time? When exactly will these things go out of scope and die? This often leads to important insights necessary for further optimizations or stronger abstraction refactors, of which would usually be completely hidden behind smart pointers.
2. Code starts to be designed in a way to localize or minimize lifetime management, in order to avoid a tangled explosion of lifetime management calls. This usually results in smarter abstractions more tailored to the problem-at-hand, which would never have manifested if all lifetime management was hidden behind a single "catch-all" smart pointer solution.

« Last Edit: October 16, 2019, 10:15:27 AM by qMopey » Logged
buto
Level 0
***



View Profile WWW
« Reply #58 on: October 16, 2019, 10:34:22 AM »

qMopey, I think you raise some interesting points. None of it is an argument against C++, I think. But it is a reminder that you have to think carefully about what you are actually implementing. To write fast and maintainable code always means that you have to use the tools at hand in an meaningful way. I think if you're doing object oriented programming, C++ gives you some really useful tools.

When it comes to serialization and deserialization of large amounts of data, using small objects that encapsulate that data, possibly even with smart_ptrs etc, quickly gives you a hard time and lots of performance and programming overhead. Thinking beforehand on how to layout data in your code and how to reference it (possibly again in an object oriented way, but without actually storing the data in objects) may simplify a lot of things.

Speaking of it - serialization of non-trivial object hierarchies is not part of C++. I'm not sure whether it should be. Probably not, for the reasons mentioned above...
Logged

qMopey
Level 6
*


View Profile WWW
« Reply #59 on: October 16, 2019, 10:46:21 AM »

@buto you’re absolutely right. I’m not arguing against the underlying motivations of C++ and RAII. I’m only arguing against how they are implemented and manifest in reality. And the reality has a lot of downsides that could be avoided with better language designs, or, with strong coding guidelines.
Logged
Pages: 1 2 [3] 4
Print
Jump to:  

Theme orange-lt created by panic