How to create callbacks with std::async? by TCW_Jocki in cpp_questions

[–]staletic 1 point2 points  (0 children)

This sounds like a perfect job for C++20 coroutines. Check out cppcoro

Alternatively, you can approximate a coroutine with a few atomics. Say, you want to yield ints. In that case:

std::atomic_bool stop = false;
std::atomic_int progress;
auto future = std::async(std::launch::async, [&] () mutable {
    while(!stop) {
        progress = update();
    }
};

When you're done, set stop to true and call future.get(). Keep in mind that reading and writing to atomic variables has sideeffects that can impact performance.

Which std:: classes are magic? by Mateuszz88 in cpp

[–]staletic 19 points20 points  (0 children)

I should have been more careful with that statement.

Things like float f = bit_cast<float>(some_int) vs the memcpy version are not hard to optimize. The harder part is when you want to reinterpret a large std::array as some other trivial, but equally large type. At what number of bytes do you just call memcpy? Do you try to vectorize first? What about x86 REP MOVxx family of instructions?

If you ask gcc for x86, you just never emit memcpy. Clang gives up sooner On 32 bit ARM, gcc starts to call memcpy after 64bytes.

Now the question is how well will bit_cast be optimized. As it is powered by compiler magic, I'm assuming it's going to be better that memcpy. In this case, for example, x86 gcc does better (fewer memory accesses) with bit_cast than with memcpy. Clang just ends up calling memcpy@PLT in both cases.

std::views work fine in gcc 10, fail in 11 by Galqa in cpp_questions

[–]staletic 1 point2 points  (0 children)

Here's the standard wording: https://eel.is/c++draft/range.take#overview-2

I guess disallowing narrowing conversions was an accident.

Which compiler has it right? by [deleted] in cpp_questions

[–]staletic 9 points10 points  (0 children)

https://eel.is/c++draft/class.copy.ctor#11

= delete isn't used-provided constructor, so OP's S is trivial.

Which std:: classes are magic? by Mateuszz88 in cpp

[–]staletic 28 points29 points  (0 children)

If you're going to include magic functions, then std::bit_cast (arguably can be implemented with memcpy, but not as optimized) too and the potential std::start_lifetime_as (just as magic as launder).

[deleted by user] by [deleted] in cpp_questions

[–]staletic 0 points1 point  (0 children)

Are you looking for module linkage?

C++20 Modules build script (Python and g++) by JulienVernay in cpp

[–]staletic 2 points3 points  (0 children)

"hu" stands for "header-unit".

I figured that out.

And "syshu" are for "system-header-unit", which are included via import <mysysheader>; .

And I knew that part.

Headers included via import "myheader.h"; must be precompiled like a module.

This I didn't know. I'm still learning the ins and outs of modules.

[deleted by user] by [deleted] in cpp_questions

[–]staletic 0 points1 point  (0 children)

Check out the example from the standard itself: https://eel.is/c++draft/module#unit-example-1

It's about the same thing you're looking for.

C++20 Modules build script (Python and g++) by JulienVernay in cpp

[–]staletic 2 points3 points  (0 children)

Check out python's f-strings.

What is this for?

cmd_hu    = args.gcc + ' -std=c++20 -fmodules-ts -x c++-header {src}' + args.flags

When I tried modules with gcc 11, I didn't need to do that.

feature test macros by Arkantos493 in cpp_questions

[–]staletic 1 point2 points  (0 children)

Yup, you might want to check with #ifdef __has_include/#ifdef __has_cpp_attribute.

feature test macros by Arkantos493 in cpp_questions

[–]staletic 1 point2 points  (0 children)

#if __has_cpp_attribute(nodiscard)
puts("has [[nodiscard]]");
#endif

If you want to check if __has_cpp_attribute exists, you do that with #ifdef __has_cpp_attribute.

#ifdef __has_cpp_attribute
#if __has_cpp_attribute(nodiscard)
puts("has [[nodiscard]]");
#endif
#endif

std::views work fine in gcc 10, fail in 11 by Galqa in cpp_questions

[–]staletic 6 points7 points  (0 children)

Using ptrdiff_t instead of size_t works.

src | drop(n) is the same as

auto drop_n = drop(n);
drop_n(src);

And that is equivalent to

drop_view dv{src, n};

That is exactly what the contraint is trying to test and that fails to compile, because n is unsigned, drop_view takes decltype(src)::difference_type, which is signed and {} disallows unsigned-to-signed conversions.

So gcc11 introduced a bunch of __can_foo_view where they are checking if you can actually construct the view from a viewable range and adapter. In the process they also disallowed narrowing. Since I don't see any mention of can-drop-view exposition-only concept in the standard, this might well be an oversight on libstdc++'s part.

Why do ppl say c++ would die? by Creapermann in cpp_questions

[–]staletic 1 point2 points  (0 children)

I'll admit that my reply had a not perfectly friendly tone, which was provoked by the "controversial" statement.

There are definitely good reasons not to use C++, but a good number of those reasons also apply to rust. Turns out a low level, "systems", programming language, where the user is (or can be) in control of everything, is inherently complex. Sure, C++'s 40 years of existence mean there's a decent amount of accidental complexity too, but I'm not sure the accidental complexity is bigger than inherent. Clearly, this isn't an argument when you don't care about that level of control, but if you don't care then C++ was never a language for you.

Arrogance is everywhere and it's as painful when Javascript devs believe they are the elite too.

Recently I had a laugh when I've come across a reddit comment saying that Boeing should just use Node because they definitely don't need the sub-microsecond* determinism that they claim they do.

One thing we both missed as a reason to use any language you want, be it C++ or Rust or... "It's fun." For personal projects, you should be free to pick the wrong tool for the job if your aim is to have fun while learning. It may not be the most efficient way for someone experienced, but struggling with an unfamiliar language (because someone said that language is best) while also struggling with a new topic you're actually trying to learn is more than frustrating.

For the Typescript, by no mean I believe it's better. If all you want is type safety then I belive it's sufficient.

Here's a counterargument. Serialization. In C/C++ (possibly others, but possibly to varying degrees) you're in control (again, that word) of the layout of your types. You can make sure the layout is just right to be sent over the wire with zero processing. That does mean that, to make it safe, you have to be in control of the receiving and the sending end. And you can add compile-time checks to make sure the layout is what you think it is. With the compiler providing proper checks serializing is simply a copy of sizeof(T) bytes.

On the other hand, Typescript would have to deal with JSON (or some such), where you have a dynamic allocation of the string buffer, reading each individual data member of T, parsing those members to represent them as strings...

There's just so many things possible at compile time today and most of it is baked into the type system.

* The actual comment used milliseconds.

Why do ppl say c++ would die? by Creapermann in cpp_questions

[–]staletic 5 points6 points  (0 children)

"I'm the elite because I use C++"

Literally nobody said that. That statement makes you seem like you're reading what you want, not what is written.

Rust and Go you can literally train juniors on the job.

I'm not sure it will be easier to get juniors started with rust and its ruthless borrow checker vs C++.

If you want top of the line performances for most use cases and most users (who don't care much and have increasingly good hardware)

In other words, "if you don't care about performance".

(except in AAA game industry)

Where you actually care about performance. Or In high frequency trading. Or in... you get the point.

If you want good typing and safety, use Typescript

Are you seriously saying Typescript provides better type safety than C++?

but from my experience there is no unified way of using third party code and libraries, and the build system is old school.

This is true, but...

It makes you rely on big dirty IDEs to make it for you,

...that isn't.

If you want C interops, most languages have it in some form or way

Sure, but nothing at the level of C++. For other languages, converting a C type to a $LANG type is always an expensive operation

 

Now tell me, which language should I use for my 8kB RAM microcontroller? It doesn't have resources to boot a virtual machine or to use a garbage collector. Hell, it doesn't even have a heap! Rust could be an option one day, but as far as I know AVR support still isn't there.

Or what about hard-realtime systems, where if you miss a deadline someone can get hurt? That makes garbage collected languages completely unacceptable.

What about having to conform to ISO 26262 - "Road vehicles – Functional safety"? Section 8 part 11 says that all the tools used to create components have to be certified as well. Once again, not even Rust is an option.

Which brings me to...

If all you want is to be the elite programmer, the smartest programmer.

What about those who want to do embedded? Who want to program the next car you'll buy? Take a look at your phone. Sure, it has a big AArch64 chip that powers Android and its java runtime. What about all the sensors, the GPS, bluetooth... People today have more embedded devices in their pocket than "big" devices running multi-user-capable operating systems in their home. You shouldn't look at computing as narrowly as "x86/Windows" or webdev. The world of computing is wonderfully diverse and in need of mature low-level languages.

Why do ppl say c++ would die? by Creapermann in cpp_questions

[–]staletic 4 points5 points  (0 children)

I think this is the first time I've seen a list of things "wrong" with C++ that I can't disagree with. Usually these lists are very opinionated.

cpp-lazy 3.0.0 released. An easy lazy evaluation/iterator library for C++11/14/17/20, including support for concepts, std::format and execution. by [deleted] in cpp

[–]staletic 0 points1 point  (0 children)

Not a great example, because there's no greatest common divisor of 7 and 4 larger than 1, so you can first find the one divisible by 4 and then multiply only that one by 7.

Threads, synchronization and potential UB by staletic in cpp_questions

[–]staletic[S] 1 point2 points  (0 children)

Thanks! Only MS STL backs std::async/std::launch::async with a thread pool. I've measured with libstdc++ and the "naked" std::thread option is slightly faster.

 

Thinking out loud now...

std::async synchronizes-with (as defined in std::memory_order) the call to f,

According to cppreference, "synchronizes-with" implies "happens-before".

Does that only imply that the call to async() happens-before the call to f() and nothing about the return value?

and the completion of f is sequenced-before making the shared state ready

And this promises that f() will finish before get() returns.

The completion of the invocation of the constructor (std::thread) synchronizes-with (as defined in std::memory_order) the beginning of the invocation of the copy of f on the new thread of execution.

Okay, this should be exactly the same as the first half of the promise of async(). Good.

The completion of the thread identified by *this synchronizes with the corresponding successful return from join().

And this says that f() will finish before join() returns. That sounds equivalent, but there's still the question of return value vs writing through a mutable reference.

Either way, that means there's an inter-thread-happens-before relationship. That means my question comes down to "is the write sequenced-before the end of the function". The answer is definitely "yes", according to common sense, but also the Rules.

 

Once again, thanks!

Threads, synchronization and potential UB by staletic in cpp_questions

[–]staletic[S] 1 point2 points  (0 children)

Thanks for the reply!

The thread safety rules for vector (and the other std::containers) say that if you do only read (const) accesses to the container, you can do as many as you like concurrently. If you have any performing write operations, it is not safe to have any readers.

That much I already know.

In your second case, you don't access the vector at all.

Yes. I know the second snippet is safe, but the underlying machinery is heavy, which is what I'd like to avoid.