Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
redleader
Aug 18, 2005

Engage according to operational parameters

qsvui posted:

lol how are you so wrong on every one of these points

c++ is every language for every developer and every use case. you just write a different subset of c++ to them. neither of you are wrong, except that you're both using c++ in the first place

Adbot
ADBOT LOVES YOU

Progressive JPEG
Feb 19, 2003

ratbert90 posted:

What the gently caress is this horse poo poo?

brb figuring out how to do numerical formatting using streams

NOT

Xarn
Jun 26, 2015

Progressive JPEG posted:

imo:
- don't use exceptions
- mark all destructors virtual
- templates are effectively a preprocessor stage
- use smart pointers everywhere (e.g. unique_ptr for members rather than raw pointers)
- don't bother with c++ streams just use the c printf stuff, unless theres something better in the last 5 years idk

Literally all of this is wrong.

e:

The one thing it gets right (avoid standard streams if possible), is still made wrong by recommending printf and its ilk.

Xarn fucked around with this message at 07:39 on Sep 2, 2018

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

DONT THREAD ON ME posted:

how should I do exception handling? I'm most comfortable with Either's and saw someone recommend using them but no idea if that's a good idea or not. I'd rather learn to do what actual real programmers programming C++ do which I'm guessing is exceptions.

you can do both! The best part is you can move between the two and your choice won't be wrong as long as you don't treat the non-exception error-handling like a C programmer who went into a coma in the 80s and woke up yesterday. One thing you'll run into is "How do I construct an object and make sure it never throws?" since you're coming from Rust you just do what Rust does. Static member function, returns an either (we call ours expected, but there's also outcome and that one is a bit better refined). Want to quickly wrap a function that *might* throw and have it turn into an expected? You get to use one of the least well known features of C++: using try blocks as function bodies

C++ code:
template <class... Args>
expected<invoke_of_t<Args...>> safe_invoke (Args&&... args) noexcept try {
  return std::invoke(std::forward<Args>(args)...);
} catch (...) { return std::current_exception(); }

struct T { int x; };

auto x = safe_invoke([] { throw &T::x; });
welcome to the nightmare :v: (im legit gonna try to remove the ability to throw a member pointer for c++20, but you can do this now if you hate life)

tbqh he community is extremely split between people who say "no, exceptions are terrible for high performance code and here's a bunch of proof and examples", people like Herb Sutter who think there's something we can do to bridge the gap (but misunderstanding error handling approaches from other languages) and then people like Bjarne who say "software engineers should write software and leave language design to designers such as myself". (remember, the vasa sank because jet fuel can't melt wooden beams)

if anything though, c++ has some decent capabilities for bridging schools of thought. private inheritance gets you mixins and composable interfaces. public inheritance gives you (in the case of a virtual destructor) class 90s OOP. protected inheritance gives you a bridge to go from public hierarchies to a private hierarchy while keeping both interfaces satisfied. (protected inheritance is "i know that myself is-a Base, but to everyone else I look like has-a Base interface")

Luigi Thirty
Apr 30, 2006

Emergency confection port.

tried to get texture mapped polygons going in glide tonight by putting an image on a cube

I got polygons that are filled with garbage so there’s something, at least I’m loading texture memory with... something and pointing the texture unit at it

the voodoo2 contains two hardware texture mapping units capable of trilinear filtering and 16-bit textures up to 256x256 with 2MB of RAM per unit, plus a blitter for accelerating CPU <-> VRAM transfers

Luigi Thirty fucked around with this message at 09:45 on Sep 2, 2018

toiletbrush
May 17, 2010
So yesterday I learnt enough Metal to port my live camera feed processing iPhone app over from the CPU to GPU. It was on CPU first because I don't know Metal at all and wanted to prove the idea works, and actually had a ton of fun getting the CPU version running as fast as I could (it does a twatty transform of a distortion into arrays of pointer increments and memcpy() parameters depending how many pixels can be copied at once)

But holy crap it only took part of the afternoon, and with some help from Instruments got CPU time down to sod-all and time to generate frames down from 18ms down to 200µs. When it first ran I was grinning like an idiot. My best terrible programmer moment of the year hands down.

As far as Metal goes it seems nice, but the docs aren't great for a noob, its like they were written for someone who already new what they were doing and just needed to brush up.

Phobeste
Apr 9, 2006

never, like, count out Touchdown Tom, man

Slurps Mad Rips posted:

one of the least well known features of C++: using try blocks as function bodies

C++ code:
template <class... Args>
expected<invoke_of_t<Args...>> safe_invoke (Args&&... args) noexcept try {
  return std::invoke(std::forward<Args>(args)...);
} catch (...) { return std::current_exception(); }

struct T { int x; };

auto x = safe_invoke([] { throw &T::x; });

holy god

DONT THREAD ON ME
Oct 1, 2002

by Nyc_Tattoo
Floss Finder

toiletbrush posted:

So yesterday I learnt enough Metal to port my live camera feed processing iPhone app over from the CPU to GPU. It was on CPU first because I don't know Metal at all and wanted to prove the idea works, and actually had a ton of fun getting the CPU version running as fast as I could (it does a twatty transform of a distortion into arrays of pointer increments and memcpy() parameters depending how many pixels can be copied at once)

But holy crap it only took part of the afternoon, and with some help from Instruments got CPU time down to sod-all and time to generate frames down from 18ms down to 200µs. When it first ran I was grinning like an idiot. My best terrible programmer moment of the year hands down.

As far as Metal goes it seems nice, but the docs aren't great for a noob, its like they were written for someone who already new what they were doing and just needed to brush up.

nice! i love that feeling

jony neuemonic
Nov 13, 2009

jony neuemonic
Nov 13, 2009

matrices clicked for me this morning and it feels extremely good.

Lime
Jul 20, 2004

Slurps Mad Rips posted:

(im legit gonna try to remove the ability to throw a member pointer for c++20, but you can do this now if you hate life)

what's specifically bad about this?

animist
Aug 28, 2018

jony neuemonic posted:

matrices clicked for me this morning and it feels extremely good.

matrices are rad

i feel like every time i pick them up i learn some new weird property they have, and then immediately forget about it

DONT THREAD ON ME
Oct 1, 2002

by Nyc_Tattoo
Floss Finder

Slurps Mad Rips posted:

you can do both! The best part is you can move between the two and your choice won't be wrong as long as you don't treat the non-exception error-handling like a C programmer who went into a coma in the 80s and woke up yesterday. One thing you'll run into is "How do I construct an object and make sure it never throws?" since you're coming from Rust you just do what Rust does. Static member function, returns an either (we call ours expected, but there's also outcome and that one is a bit better refined). Want to quickly wrap a function that *might* throw and have it turn into an expected? You get to use one of the least well known features of C++: using try blocks as function bodies

C++ code:
template <class... Args>
expected<invoke_of_t<Args...>> safe_invoke (Args&&... args) noexcept try {
  return std::invoke(std::forward<Args>(args)...);
} catch (...) { return std::current_exception(); }

struct T { int x; };

auto x = safe_invoke([] { throw &T::x; });
welcome to the nightmare :v: (im legit gonna try to remove the ability to throw a member pointer for c++20, but you can do this now if you hate life)

tbqh he community is extremely split between people who say "no, exceptions are terrible for high performance code and here's a bunch of proof and examples", people like Herb Sutter who think there's something we can do to bridge the gap (but misunderstanding error handling approaches from other languages) and then people like Bjarne who say "software engineers should write software and leave language design to designers such as myself". (remember, the vasa sank because jet fuel can't melt wooden beams)

if anything though, c++ has some decent capabilities for bridging schools of thought. private inheritance gets you mixins and composable interfaces. public inheritance gives you (in the case of a virtual destructor) class 90s OOP. protected inheritance gives you a bridge to go from public hierarchies to a private hierarchy while keeping both interfaces satisfied. (protected inheritance is "i know that myself is-a Base, but to everyone else I look like has-a Base interface")

interesting. I'm curious about the public/private/protected forms of inheritance, that's new to me. cheers!


Xarn posted:

Literally all of this is wrong.

e:

The one thing it gets right (avoid standard streams if possible), is still made wrong by recommending printf and its ilk.

what's wrong with smart pointers? I'm not really using them yet because I want to get experience with raw pointers but I figured modern C++ was all about the smart pointers.

Beamed
Nov 26, 2010

Then you have a responsibility that no man has ever faced. You have your fear which could become reality, and you have Godzilla, which is reality.


DONT THREAD ON ME posted:

what's wrong with smart pointers? I'm not really using them yet because I want to get experience with raw pointers but I figured modern C++ was all about the smart pointers.
it was when i was last writing c++ in 2015, so I'm curious to know if the community moved hard against 'em like they did another cool C++11 feature

Xarn
Jun 26, 2015

DONT THREAD ON ME posted:

interesting. I'm curious about the public/private/protected forms of inheritance, that's new to me. cheers!

It is pretty much the same as the public/private/protected specifiers, but applied to the fact that the class is inheriting form a base. https://godbolt.org/z/lMdYJt


DONT THREAD ON ME posted:

what's wrong with smart pointers? I'm not really using them yet because I want to get experience with raw pointers but I figured modern C++ was all about the smart pointers.

They are perfectly OK, when you use them correctly (e.g. shared_ptr tends to be overused as gently caress), but it is a lovely advice, because it leads to code like this

code:
auto vec = std::make_unique<std::vector<int>>();
vec->push_back(123);
vec->push_back(456);
and increases general pointer-chasiness of code, when the proper advice is "use the gently caress out of RAII" and the code is supposed to be

code:
std::vector<int> vec;
vec.push_back(123);
vec.push_back(456);
Basically, you should have a positive reason to use a pointer, instead of placing the object directly onto stack/making it direct part of the object's layout.

qsvui
Aug 23, 2003
some crazy thing
Also, raw pointers are fine if they are non-owning which means you shouldn't have functions that look like this:

code:
void f(const std::unique_ptr<SomeResource>& p)
{
  // Not changing ownership of whatever p points to
}
Just do this:

code:
void f(SomeResource* p)
{
  // Read/write what p points to
}
and use the get() member to retrieve the raw pointer from your smart pointer.

redleader
Aug 18, 2005

Engage according to operational parameters

Phobeste
Apr 9, 2006

never, like, count out Touchdown Tom, man

Xarn posted:



Basically, you should have a positive reason to use a pointer, instead of placing the object directly onto stack/making it direct part of the object's layout.

yeah i think when most people say "always use smart pointers" i think they mean "for owning references that are dynamically allocated rather than using raw pointers", not instead of reference types or stack allocations

Progressive JPEG
Feb 19, 2003

Phobeste posted:

yeah i think when most people say "always use smart pointers" i think they mean "for owning references that are dynamically allocated rather than using raw pointers", not instead of reference types or stack allocations

ya

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
if you ever use shared_ptr, you've hosed up somehow

it's possible that shared_ptr is the best way to resolve your immediate problem, but that just means the root fuckup was so long ago that it's now a pain to fix

gonadic io
Feb 16, 2011

>>=

Jabor posted:

if you ever use shared_ptr, you've hosed up somehow

it's possible that shared_ptr is the best way to resolve your immediate problem, but that just means the root fuckup was so long ago that it's now a pain to fix

i was about to disagree but then i realised just how long since i last used Box::new in rust. strings and vecs get put on the heap all the time but that's only because of their variable size - none of my structs ever need to go on the heap

gonadic io
Feb 16, 2011

>>=
maybe i should start using cow/smallvec more

reptilians
Sep 2, 2018



i've been triyng to learn more rust and i feel like the error messages are kind of opaque. like in this guy's example of making a linked list stack:

code:
pub fn push(&mut self, elem: i32) {
    let new_node = Box::new(Node {
        elem: elem,
        next: self.head,
    });

    self.head = Link::More(new_node);
}
he explains that the code will return this error
code:
src/first.rs:19:10: 19:14 error: cannot move out of borrowed content
src/first.rs:19           next: self.head,
                                ^~~~
but if you swap the memory out first it gets past the borrow checker:

code:
pub fn push(&mut self, elem: i32) {
    let new_node = Box::new(Node {
        elem: elem,
        next: mem::replace(&mut self.head, Link::Empty),
    });

    self.head = Link::More(new_node);
}
i suspect the true reason the first one is bad is that throwing an exception before the last line would leave you with a partially created linked list but it's not really explained.

DONT THREAD ON ME
Oct 1, 2002

by Nyc_Tattoo
Floss Finder
the reason the borrowchecker is failing is because it is illegal to move out of borrowed content in rust. it's one of the rules of the language. it's not aware of why it's bad. so yeah, it's absolutely opaque. i agree.

gonadic io posted:

i was about to disagree but then i realised just how long since i last used Box::new in rust. strings and vecs get put on the heap all the time but that's only because of their variable size - none of my structs ever need to go on the heap

hey this is confusing me. what's the relationship between shared_ptr and Box in rust?

DONT THREAD ON ME fucked around with this message at 04:13 on Sep 3, 2018

eschaton
Mar 7, 2007

Don't you just hate when you wind up in a store with people who are in a socioeconomic class that is pretty obviously about two levels lower than your own?
why did Rust go with its memory model instead of something like ARC where the semantics are a bit less opaque?

comedyblissoption
Mar 15, 2006

eschaton posted:

why did Rust go with its memory model instead of something like ARC where the semantics are a bit less opaque?
performance

you can still do RC (reference counted) and ARC (atomic reference counted) in rust

a language implicitly doing some garbage collection or reference counting strategy for you incurs memory and cpu overhead that is not appropriate for the type of programming niche rust wants to fill

comedyblissoption fucked around with this message at 05:11 on Sep 3, 2018

comedyblissoption
Mar 15, 2006

rust's borrow rules also improve program correctness beyond what garbage collection and reference counting schemes offer

the rules statically prevent you from incorrectly read or writing to data that you should not in certain scopes. some prominent examples:
  • if you are in the middle of iterating on a vector, the borrow rules statically prevent you from incorrectly adding elements to the vector.
  • if you've moved data, you are not allowed to use the old reference anymore
  • the rules statically prevent shared memory race conditions in concurrent programs
  • if you have a reference to an element of the vector and someone pushes to the vector, rust forbids this because the alternative is a use after free bug. this problem can crop up whenever you alias memory in c++. garbage collection/reference counting can prevent this one

in c++/java, violation of these rules can cause undefined behavior that you don't know about or a program exception

rust's rules also encourages a design with less shared mutable and less global state. this probably improves programmer productivity

some articles about this:
https://manishearth.github.io/blog/2015/05/03/where-rust-really-shines/
https://manishearth.github.io/blog/2015/05/17/the-problem-with-shared-mutability/

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

DONT THREAD ON ME posted:

the reason the borrowchecker is failing is because it is illegal to move out of borrowed content in rust. it's one of the rules of the language. it's not aware of why it's bad. so yeah, it's absolutely opaque. i agree.


hey this is confusing me. what's the relationship between shared_ptr and Box in rust?

the same relationship between Arc and Box in rust. except we don’t have an Rc, though my retain_ptr paper might pave the way for one eventually.

eschaton posted:

why did Rust go with its memory model instead of something like ARC where the semantics are a bit less opaque?

with retain_ptr I can do whatever I want with ObjC's ARC bullshit and I can just let implicit copies happen whenever. i bow before no mortal

Slurps Mad Rips fucked around with this message at 06:09 on Sep 3, 2018

Luigi Thirty
Apr 30, 2006

Emergency confection port.

smart pointers? lambdas? sorry can’t hear you VC6 barely has the ++ part down

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

Luigi Thirty posted:

smart pointers? lambdas? sorry can’t hear you VC6 barely has the ++ part down

tbqh it’s more or less on par with gcc 2.95 which was its main competition when they were released

i need to go find that patch someone did to the half life 1 sdk so you could make mods with gcc 2.95

Luigi Thirty
Apr 30, 2006

Emergency confection port.

iirc GCC 2.95 is the latest one you can get working on basically every platform that can semi-emulate POSIX so there’s something

Xarn
Jun 26, 2015
Every time I hear horror stories about old gcc or old VS, I am so glad I started doing C++ with VS2010...

Luigi Thirty
Apr 30, 2006

Emergency confection port.

oh yeah I love VS2017. Microsoft tools own shaggar was right etc etc

gonadic io
Feb 16, 2011

>>=

DONT THREAD ON ME posted:


hey this is confusing me. what's the relationship between shared_ptr and Box in rust?

Unless I completely misunderstood, there was some previous chat about how you should only use unique_pointer when referring to a newly created heap value and then it has similar semantics as a borrow-checked Box.

reptilians posted:

i've been triyng to learn more rust and i feel like the error messages are kind of opaque. like in this guy's example of making a linked list stack:

code:
pub fn push(&mut self, elem: i32) {
    let new_node = Box::new(Node {
        elem: elem,
        next: self.head,
    });

    self.head = Link::More(new_node);
}
i suspect the true reason the first one is bad is that throwing an exception before the last line would leave you with a partially created linked list but it's not really explained.

Self.head does not implement copy here so when you put it inside the box (instead of a reference/pointer) you'd completely invalidate the old memory but you only have a mutable ref to it which is not allowed.

If you could freely copy self.head, or if the function took self.head by value (you'd be free to destroy the old value) there'd be no issue. If it was cloneable then instead of calling replace you'd call clone. Instead since self.head is uncopyable you need to move it out and leave some value in its place.

Note that the question is now why do uncopy/cloneable values exist and I'm not 100% on that. Copy is a bitwise copy so you're not allowed to do it with pointers that are supposed to be unique (vec, box, etc). Those need to be deep copied (ie cloned) or references used.

Very few things aren't cloneable - mutable references are one because then you'd be bypassing the borrow checker. Idk what else.

Final note: even if the value was cloneable, since you're overwriting the old value anyway it'd be a waste to deep copy it so it might be worth using replace anyway. A common trick is replacing with uninitialized mem to avoid the cost of constructing a default instance of the type but then you're in unsafe land and you better be really sure you need those cycles and will never tweak that code into ub.

bob dobbs is dead
Oct 8, 2017

I love peeps
Nap Ghost
the cto of the place i'm at was high up at microsoft
dragged like 9 of his microsoft buddies to shore up a previously-10-peep engineering team. they do honestly better work than the old peeps cuz it turns out tech majors (former tech majors, i guess?) have hiring standards. i was another student of the prof whose spinoff this is so i got in by nepotism (lol no)

we use postgres and goog cloud, lol. by cto's choice

(but we use c# and vs2017)

Fiedler
Jun 29, 2002

I, for one, welcome our new mouse overlords.
- ballmer-era microsoft high-up
- makes bad decisions

yes this all checks out

gonadic io
Feb 16, 2011

>>=
Note that it's entirely possible to turn the borrow-checked from statically checked to runtime checks using the *rc and *cell types. You can further bypass those runtime checks by using the unchecked methods in those types, poo poo or even just casting to mut* and doing whatever the gently caress (the last two require unsafe blocks) you want but those practices are strongly discouraged.

There's plugin's tracking the use of unsafe in libraries and fuzzing them and people who go around making pull requests to remove them if at all possible because you really do lose all of rust's guarantees if you do that poo poo.

IMO the way to do unsafe programming in rust is to be aware of which invariants you're promising to maintain.

Going into unsafe to use mem::uninitialized because you really can't pay the cost of constructing a valid instance of the type? Better be loving sure you write to it (note that dropping uninitialized memory is not allowed because you don't know what Drops will run on it.

Dereferencing a static memory address for a peripheral? Better be loving sureit's valid. Converting that pointer into a ref? Now you've just promised "the aliasing and mutability laws of references" are true for that pointer.

gonadic io fucked around with this message at 09:05 on Sep 3, 2018

Progressive JPEG
Feb 19, 2003

Jabor posted:

if you ever use shared_ptr, you've hosed up somehow

it's possible that shared_ptr is the best way to resolve your immediate problem, but that just means the root fuckup was so long ago that it's now a pain to fix

returning a large heap allocated object?

Jabor
Jul 16, 2010

#1 Loser at SpaceChem

Progressive JPEG posted:

returning a large heap allocated object?

if the caller is going to be taking ownership, return a unique_ptr. if not then return a raw pointer or a reference.

if you don't know who's supposed to have ownership, and one might be cleaned up before the other one is finished with the large object you've returned, then

Jabor posted:

that just means the root fuckup was so long ago that it's now a pain to fix

Adbot
ADBOT LOVES YOU

eschaton
Mar 7, 2007

Don't you just hate when you wind up in a store with people who are in a socioeconomic class that is pretty obviously about two levels lower than your own?

comedyblissoption posted:

performance

you can still do RC (reference counted) and ARC (atomic reference counted) in rust

a language implicitly doing some garbage collection or reference counting strategy for you incurs memory and cpu overhead that is not appropriate for the type of programming niche rust wants to fill

ARC = Automatic Reference Counting, which generally means implementing the Cocoa/ObjC reference counting and ownership model

(Swift’s ARC is slightly different in that the general case of a returned value is +1 (retained, caller-release) rather than +0 (retained, callee-autoreleased), but is extremely similar overall)

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply