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
Xarn
Jun 26, 2015

rjmccall posted:

As a language designer, I think the right rule is that expression results should default to not being discardable, and functions should have to opt out of that.

Yeah, at my last place we annotated 90+% of all our functions with [[nodiscard]] and we had no problems with it. The rest were mostly void functions :v:




rjmccall posted:

It seems obvious that you could borrow that same funny wording for the standard library's specifications of e.g. c.empty() and c.size() and get the point across without crossing any novel lines like implying that standard library types have member functions. I don't know why anyone would have a problem with that, but it's the C++ committee, so I'm not surprised that somehow this turned into a major fight.

So, right now the specification of bunch of things actually uses discard in the standard, e.g.
C++ code:
[[nodiscard]] static unsigned int hardware_concurrency() noexcept;
There were some papers about adding these to more places, based on experience with MSVC STL (who are adding nodiscard fairly aggressively and have had good experience with it). This lead to long-rear end discussion about the papers, with arguments like

  • We need a Grand Unified Rule About Nodiscard before we add more annotations into standard
  • nodiscard doesn't belong into standard at all because it is only Quality Of Implementation and doesn't have normative effect
  • But what if we annotate standard container's size, someone writes their own container, annotates size with nodiscard, but the implementation is caching, and someone writes generic code where they just call container::size to precache the results, and they don't want to explicitly suppress the warning, and and and and I still do not believe that was a good faith argument :suicide:
  • The paper is a waste of LEWG's time because it is too small
  • The paper is a waste of LEWG because see 1 (and or 2)

The result is lot of wasted time in discussion, a paper that suggests removing all existing instances of nodiscard in the standard and lot more wasted time by discussing this new paper in actual meeting.


Basically every time I am thinking that maybe I could contribute paper once again, this poo poo happens and I decide that nah, this is not worth it :v:


----------------- e ------------
What a great way to start new page.

Adbot
ADBOT LOVES YOU

Xarn
Jun 26, 2015

Is the question how to detect a cycle in graph induced over votes in some election?

Ranidas
Jun 19, 2007

Xarn posted:

Is the question how to detect a cycle in graph induced over votes in some election?

Yes, and what I'm doing wrong in my approach to a recursive function to do so.

I feel like I have the core of the mechanism right, but can't figure out a way to implement it without return path issues.

Of course I could be wrong and maybe I'm not anywhere close!

Xarn
Jun 26, 2015
You need to keep around some extra information, specifically already visited nodes. Usually you will keep around simple array where you mark a node as visited when you recurse down, and unmark it when you recurse up. If you are about to recurse down a find out that node is already marked, then you've ran into a cycle.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
Ahhh good old pointers and references. Now I'm starting to get back into the groove.

Suppose you are getting a list of names from some kernel module using a helper function. The result would be an int for number of records, a char* for the buffer (that the caller frees), and char** for all the different names in the buffer (that the caller frees). Ahhh, but you need to pass references to all these so suddenly it's int*, char**, char***. Time for a nap!

duck monster
Dec 15, 2004

Volguus posted:

I always hated begin and end and typing := (although it's easier and clearer to read).

Honestly its a lot easier to follow than curly brackets.

And less easy to follow than indentation based block structuring.

I think its just a matter of what your comfortable with. I grew up on pascal (and basic, but I chose to forget the 80s. Bad hair. Bad music. Bad language) so it was natural for me, and I found curly brackets intimidating. Until eventually I didn't.

Computer viking
May 30, 2011
Now with less breakage.

My pet theory is that language designers pick syntax that's easy to type on their keyboards - and Wirth is Swiss, which means curly brackets are altGr symbols and a bit annoying to type all the time. Forward slash is shift+7 and asterisk shift+3, which means pascal (* comments *) are not significantly worse than C /* comments */ .

Of course, he may well have done all his work on a US keyboard, which would entirely invalidate that theory.

E: it does look like the machine he designed along with the Oberon language has a US style layout in the Wikipedia image, at least. Oh well.

Computer viking fucked around with this message at 22:35 on Aug 10, 2021

duck monster
Dec 15, 2004

Computer viking posted:

My pet theory is that language designers pick syntax that's easy to type on their keyboards - and Wirth is Swiss, which means curly brackets are altGr symbols and a bit annoying to type all the time. Forward slash is shift+7 and asterisk shift+3, which means pascal (* comments *) are not significantly worse than C /* comments */ .

Of course, he may well have done all his work on a US keyboard, which would entirely invalidate that theory.

E: it does look like the machine he designed along with the Oberon language has a US style layout in the Wikipedia image, at least. Oh well.

Its more to do with history.

WIrth was one of the people behind Algol, and was behind PL360 so when Pascal came out in 1970, its natural he would go with the prevailing standards of the era and use BEGIN and END.

When C came out a couple of years later, Richie and Thomson lifted them from B which came out in 69 but was not really known of outside their own lab.

I actually prefer pascal comments. ( ) and * are all next to each other whereas / and * are oposite sides (vertically) of the keyboard on the same hand. A little less finger stretching.

duck monster fucked around with this message at 07:32 on Aug 11, 2021

more falafel please
Feb 26, 2005

forums poster

I have a very weird situation where I learned C on the old MacOS, where the OS, libraries, docs, and samples were written in Pascal. I probably should have just learned Pascal, but compilers cost money, and I had MetroWerks CodeWarrior already.

baby puzzle
Jun 3, 2011

I'll Sequence your Storm.
I'm trying to get at most three decimal places after the period on a float.

Everything I find tells me to use std::setprecision()

code:
	std::stringstream ss;
	ss << std::setprecision( 3 ) << 1000.0f;
But this produces "1e+03" when I want "1000"

Can I simply limit the number of decimal places? setprecision() seems to be limiting the overall precision.

Xerophyte
Mar 17, 2008

This space intentionally left blank
Streams are initialized as defaultfloat, which switches to scientific notation whenever the number of digits exceeds the requested precision. 1000 is four digits, and 4 > 3 :v:. std::setprecision(4) would do what you want.

There's a std::fixed manipulator you can use to force fixed output. In that mode precision is the number of decimals, so
code:
	ss << std::setprecision(0) << std::fixed << 1000.0f;
would output "1000" to the stream.

Zopotantor
Feb 24, 2013

...und ist er drin dann lassen wir ihn niemals wieder raus...

Computer viking posted:

My pet theory is that language designers pick syntax that's easy to type on their keyboards - and Wirth is Swiss, which means curly brackets are altGr symbols and a bit annoying to type all the time. Forward slash is shift+7 and asterisk shift+3, which means pascal (* comments *) are not significantly worse than C /* comments */ .

Of course, he may well have done all his work on a US keyboard, which would entirely invalidate that theory.

E: it does look like the machine he designed along with the Oberon language has a US style layout in the Wikipedia image, at least. Oh well.

Pascal's original comment syntax actually used { curly braces }. The digraphs (* *) were meant to be used on systems that didn't have them.
code:
The construct :

   { <any sequence of symbols not containing "} ">}

may be inserted between any two identifiers, numbers, or special symbols. It is called a comment and may be removed from the program text without altering its meaning. The symbols { and } do not occur otherwise in the language, […]
(On systems where the curly brackets are unavailable, the character pairs (* and *) are used in their place.)
Source: Pascal User Manual and Report, 2nd ed., 1975.

Computer viking
May 30, 2011
Now with less breakage.

Huh, I did not know that.

PittTheElder
Feb 13, 2012

:geno: Yes, it's like a lava lamp.

Question about replacing macros, static analysis tools hate (most of) them for good reason, but I'm unsure of what the best replacement is. Define a bunch of static inline functions for all required types, possibly with a macro'd _generic access, or a single templated version? Does it even matter?

Xarn
Jun 26, 2015
What kind of macros? What are they doing?

more falafel please
Feb 26, 2005

forums poster

Xarn posted:

What kind of macros? What are they doing?

This. Macros (the language feature) are evil. Macros (the things in your codebase) are probably suspect, but not necessarily a problem. There's lots of situations where macros are, actually, the best option.

Beef
Jul 26, 2004
Coming from a Lisp background, I always hesitate to call them macros. Let's just #define macro text_replacement.

PittTheElder
Feb 13, 2012

:geno: Yes, it's like a lava lamp.

Xarn posted:

What kind of macros? What are they doing?

Mostly basic stuff, min, max, abs, squares, cubes, root sum squares.

Things that could be and should be done in real functions, but I'm mostly curious if there's a performance cost of switching them to templates.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
Is there an open source telemetry tool that works in ANSI C? We could use it for internal megacorp tools but this team has some olds obsessed with using some vetted, public one.

It looks to me like tracking on the system is just anathema to the whole open source culture, so there are some toys out there, but nothing I could act like is popular and we'll supported.

yippee cahier
Mar 28, 2005

PittTheElder posted:

Mostly basic stuff, min, max, abs, squares, cubes, root sum squares.

Things that could be and should be done in real functions, but I'm mostly curious if there's a performance cost of switching them to templates.

Same performance. Take a look at the implementation of std::min as an example. Probably looks identical to your macro. It’s inlined. The only difference is the parameters’ types are enforced by the compiler.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
That's actually a funny example because for a very long time std::min() was really slow in VC++. It is now finally fixed, though.

Xarn
Jun 26, 2015
C++ code:
int _km;                           // reserved
void operator"" _km(long double);  // not reserved
void operator"" _Km(long double);  // reserved: underscore followed by capital
void operator"" __km(long double); // reserved: contains double underscore
void operator""_Km(long double);   // not reserved
void operator""__km(long double);  // not reserved
This loving language.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
Is there a convention in C for communicating that a pointer is referring to a value the function will allocate and the user must free? This kind of thing is kind of lovely but I'm not always dealing with atomic calls where they can call once to get a size, allocate it themselves, and then call again with the buffer. That would be more ideal because the mallocs and frees properly pair.

All I can really lean on is "writing some sentences" which is fine but I was hoping at least for a function header standard or term to use on stuff like that and get into the habit of using that too.

chglcu
May 17, 2007

I'm so bored with the USA.

Rocko Bonaparte posted:

Is there a convention in C for communicating that a pointer is referring to a value the function will allocate and the user must free? This kind of thing is kind of lovely but I'm not always dealing with atomic calls where they can call once to get a size, allocate it themselves, and then call again with the buffer. That would be more ideal because the mallocs and frees properly pair.

All I can really lean on is "writing some sentences" which is fine but I was hoping at least for a function header standard or term to use on stuff like that and get into the habit of using that too.

Dunno about convention, but in C when I provide a create function, I also provide a destroy, even if it just calls free. This also allows you to easily change the allocation strategy without hunting down all the frees you need to change.

e: I also try to put the create and destroy function declarations near each other and mention the destroy function in the documentation of the create function. That’s worked well enough for me.

chglcu fucked around with this message at 06:19 on Aug 19, 2021

leper khan
Dec 28, 2010
Honest to god thinks Half Life 2 is a bad game. But at least he likes Monster Hunter.

chglcu posted:

Dunno about convention, but in C when I provide a create function, I also provide a destroy, even if it just calls free. This also allows you to easily change the allocation strategy without hunting down all the frees you need to change.

e: I also try to put the create and destroy function declarations near each other and mention the destroy function in the documentation of the create function. That’s worked well enough for me.

I also do this. It seems to work pretty well. I've also sometimes included custom allocator support via function pointer parameter for alloc/free.

Twerk from Home
Jan 17, 2009

This avatar brought to you by the 'save our dead gay forums' foundation.
Can somebody direct me towards best practices for C project organization? I keep just seeing a ton of .c and .h files in a flat directory, and thinking there must be a better way to do this.

Phobeste
Apr 9, 2006

never, like, count out Touchdown Tom, man

Twerk from Home posted:

Can somebody direct me towards best practices for C project organization? I keep just seeing a ton of .c and .h files in a flat directory, and thinking there must be a better way to do this.

Honestly just do the same poo poo as you would in any other language. Separate your functionality logically into separatable modules that hold contracts with each other, separate the files along the same lines, etc. Just like you would in python or anything else. Could do worse than looking at big c projects like the linux kernel or systemd or something.

Twerk from Home
Jan 17, 2009

This avatar brought to you by the 'save our dead gay forums' foundation.

Phobeste posted:

Honestly just do the same poo poo as you would in any other language. Separate your functionality logically into separatable modules that hold contracts with each other, separate the files along the same lines, etc. Just like you would in python or anything else. Could do worse than looking at big c projects like the linux kernel or systemd or something.

Awesome, thanks for this. https://github.com/systemd/systemd/blob/main/docs/ARCHITECTURE.md is exactly the kind of thing that I was looking for, even though the projects I'm dealing with are unlikely to get to a fraction of the size.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
I could've sworn there was a whitepaper out there about library-oriented development in LLVM, but yeah, the general idea of Always Be Writing A Library isn't a bad one. You should always be thinking about interfaces between subsystems and who has responsibility for what, and if you do that, you'll find it natural enough to split subsystems into their own directories. The three caveats:
  • Don't over-abstract just because "it's a library". If you don't have a use-case for the thing to be super-generic, don't make it generic.
  • Libraries can have dependencies. You don't have to make every subsystem interface an indirected-to-hell monstrosity so that you can theoretically play building blocks with them later.
  • Try to avoid reifying library structure into build-product structure. Just because you've made different libraries doesn't mean you have to separately link them. Assembling things into a linked image is the place where it's appropriate to play with building blocks.

Subjunctive
Sep 12, 2006

✨sparkle and shine✨

rjmccall posted:

  • Don't over-abstract just because "it's a library". If you don't have a use-case for the thing to be super-generic, don't make it generic.
  • Libraries can have dependencies. You don't have to make every subsystem interface an indirected-to-hell monstrosity so that you can theoretically play building blocks with them later.
  • Try to avoid reifying library structure into build-product structure. Just because you've made different libraries doesn't mean you have to separately link them. Assembling things into a linked image is the place where it's appropriate to play with building blocks.

Mozilla really needed you in 1999!

Sweeper
Nov 29, 2007
The Joe Buck of Posting
Dinosaur Gum
Does anyone have a link to an enum set and map utility? We have a bunch of dense enums we make tables based on for some reasonably high perf code and I’m tired of writing switch statements to map enums to structures. I wrote my own based on bitset (for set) and an array for the map values, but I’d prefer something someone else maintains if possible.

Having trouble searching for it, maybe no one has this issue and I’m inventing solutions to problems which don’t exist?

ultrafilter
Aug 23, 2007

It's okay if you have any questions.


Look into X macros.

Sweeper
Nov 29, 2007
The Joe Buck of Posting
Dinosaur Gum

I should have mentioned modern c++, we use some x macros, but tbh it feels a bit grodier than a nice constexpr map with all the nice collections stuff you get with typical c++ structures.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
Those implementations seem reasonable enough, although I guess you could use a fixed-width bitset/array if you knew the bounds if the enum. Is that what you want, something metaprogrammed to do that optimization, or do you just want something that does the casts for you?

Sweeper
Nov 29, 2007
The Joe Buck of Posting
Dinosaur Gum

rjmccall posted:

Those implementations seem reasonable enough, although I guess you could use a fixed-width bitset/array if you knew the bounds if the enum. Is that what you want, something metaprogrammed to do that optimization, or do you just want something that does the casts for you?

I’m manually passing the bounds (we have the max for everything), so that’s fine and it’s all fixed width. Just seeing if I missed something that does this for me and I could search well enough. Something dealing with casts and handles filling out the while map/container interface for me so I don’t have to do it myself would be nice. There are always little gotchas with these sorts of things and I’d rather someone else thought about them, if possible.

This just seems like the kind of micro optimization someone would have done somewhere already, so I’m surprised I can’t find it. Maybe it’s too micro even for c++ template loves :v:

qsvui
Aug 23, 2003
some crazy thing
Maybe magic_enum might help? It doesn't give you sets and maps out of the box but it may serve as a building block.

nelson
Apr 12, 2009
College Slice

Sweeper posted:

I’m manually passing the bounds (we have the max for everything), so that’s fine and it’s all fixed width. Just seeing if I missed something that does this for me and I could search well enough. Something dealing with casts and handles filling out the while map/container interface for me so I don’t have to do it myself would be nice. There are always little gotchas with these sorts of things and I’d rather someone else thought about them, if possible.

This just seems like the kind of micro optimization someone would have done somewhere already, so I’m surprised I can’t find it. Maybe it’s too micro even for c++ template loves :v:

I am not enough of a C++ expert to know if what you want is built in, but if you’re doing the same thing over and over you might consider a code generation template. Our group used jinja to generate C++ code and it seemed to work well. Certainly better than doing everything by hand.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
I don’t know of a library for exactly that off-hand. We do have one in the Swift compiler that assumes the enumerator values are already shifted.

Twerk from Home
Jan 17, 2009

This avatar brought to you by the 'save our dead gay forums' foundation.
Is https://github.com/DLTcollab/sse2neon a decent way to go for getting code that is directly importing SSE intrinsics (<emmintrin.h>) working on arm64?

I'm just shoving it in there like this. Things are building & running, but I don't have great confidence that I'm using the appropriate type of ARM uarch or the full SIMD capabilities of the Apple M1 & friends.
code:
#ifdef __AARCH64_SIMD__
#include "sse2neon.h"
#else
#include <emmintrin.h>                 // Define SSE2 intrinsics. Will fail on ARM
#endif

Adbot
ADBOT LOVES YOU

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I have multiple variables packed together in a memory buffer that I'd like to assign to a struct. Are there any gotchas for this beyond some basic memory alignment stuff? What I want to assume is:

1. The memory for a struct is going to start at a proper alignment.
2. The amount of padding then depends on the next variable in the struct. It would be aligned on cleanly divisible boundaries based on that type's width. So a char and then a (32-bit) int would imply I have to skip 3 bytes before dealing with the integer in the struct.

I know the actual schema of the data when I'm doing this.

I didn't know if there was any other major things to worry about before I create a segfault generator here. Also, I'd rather not get into X instead of Y either unless you want to read a pile on how I got here.

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