Live data from Hacker News

C++ Patterns: The Badge

awesomekling.github.io

101–110 of 160 posts

Re: C++ Patterns: The Badge

#101
post #40

Earlier quoted context omitted.

The best guard against unintended uses that hamstring the maintenance of the library is the good old opaque handle: typedef struct foo_struct *foo; foo foo_make(); void foo_destroy(foo); void foo_frobnicate(foo, int how); The client executables have no idea how big a foo object is, or what alignment requirements are, let alone what its members might be. The client executables don't control the allocation, constructio…

That doesn't solve the problem the OP solves, which is to expose a method only to a specified set of other classes.

It solves the problem by decoupling the public interface and necessary implementation details (object size), the register/unregister functions can be moved to an internal only header file, maybe even some file scoped functions. AFAIK this is not possible with a class declaration.

I think you could also solve this specific problem with an internal header file in c++ too (by moving register/deregister to it's own class) but this solution solves other problems like binary compatibility.

Re: C++ Patterns: The Badge

#102
post #99

I used to carefully design my C++ code with public / private / protected / friend (and the pointer-to-impl pattern for "compile time private") but a few years ago I started doing everything all-public ala python (struct instead of class by default) with occasionally an m_ prefix for "intended to be private", and I've never looked back. It's been great, made my programming life much easier. This badge thing is clever,…

> but a few years ago I started doing everything all-public This is a recipe for disaster as soon as inheritance is in the picture.

Everything is a recipe for disaster one inheritance is in the picture :)

Re: C++ Patterns: The Badge

#103
In D, you can access private members of a class within a single module. I like it, because it allows to move methods outside of the class, but doesn't require explicit friend declarations. And you still have the data protection because other modules can't access the private fields.

Re: C++ Patterns: The Badge

#104

Earlier quoted context omitted.

> I started doing everything all-public ala python (struct instead of class by default) with occasionally an m_ prefix for "intended to be private", and I've never looked back. This is the sort of accidental complexity that access specifiers eliminated, but somehow you managed to reintroduce by trying to reinvent the wheel. The 'm_' prefix only means "private member variable, don'access it" to you and you alone, and…

Python has a well-established convention of _underscore for intended-to-be-private members, with no enforcement, and it works fine. Just document your conventions. The horrors of some other programmer using it wrong seem overblown to me. In my IDE in c++ I can quickly refactor m_ to non-m to make it "semantically public" without having to edit header files, change struct packing order / ABI, etc. And most of the time…

Those access modifiers are there for a reason and they work very well in not just C++ in many other object oriented languages like C# and Java. So, using Python to justify that style of coding is a far cry from anything that is reasonable. If it work for you that's fine, but I don't think it's a good idea generally.

Re: C++ Patterns: The Badge

#105

In D, you can access private members of a class within a single module. I like it, because it allows to move methods outside of the class, but doesn't require explicit friend declarations. And you still have the data protection because other modules can't access the private fields.

Maybe C++ could add this feature at some point now that it too will get modules.

Re: C++ Patterns: The Badge

#106
post #80

Earlier quoted context omitted.

In larger codebases with many developers, attention to the API is required in order to be able to maintain code without breaking clients. The main downside of Badge is that it comes with a performance penalty and ABI change for something that should be statically deducible (empty struct is one byte in C++).

There is no performance penalty in any modern compiler that I am aware of (effectively no code will be emitted). You can have a look here: https://godbolt.org/z/DmeYL-

Sure within a single compilation unit. Otherwise, I like dearrifling's suggestion.

Re: C++ Patterns: The Badge

#107
post #95

I used to carefully design my C++ code with public / private / protected / friend (and the pointer-to-impl pattern for "compile time private") but a few years ago I started doing everything all-public ala python (struct instead of class by default) with occasionally an m_ prefix for "intended to be private", and I've never looked back. It's been great, made my programming life much easier. This badge thing is clever,…

Everything public versions poorly when you can't update all clients of your code after you change your implementation. It increases coupling in ways you can't control. It also doesn't work very well with code completion - implementation methods get mixed up with surface API - and usability by third parties suffers. If you're on a team of one, and you own the project for its whole lifetime, then you're fine.

The implicit contract is that anybody who uses m_ "intended to be private" members is responsible for fixing breakage.

Re: C++ Patterns: The Badge

#108
post #95

I used to carefully design my C++ code with public / private / protected / friend (and the pointer-to-impl pattern for "compile time private") but a few years ago I started doing everything all-public ala python (struct instead of class by default) with occasionally an m_ prefix for "intended to be private", and I've never looked back. It's been great, made my programming life much easier. This badge thing is clever,…

Everything public versions poorly when you can't update all clients of your code after you change your implementation. It increases coupling in ways you can't control. It also doesn't work very well with code completion - implementation methods get mixed up with surface API - and usability by third parties suffers. If you're on a team of one, and you own the project for its whole lifetime, then you're fine.

Admittedly my use case is generally projects that are under my control.

But in the case of say an open source library, how likely are clients going to update their code with each new release of the library? Typical case is to do it from time to time, especially with compiled code / shared libs, and expect a few incompatibilities to sort out and fix when you do.

In a fast evolving large team project, seems it depends on how well the boundaries of the subsystems are worked out. Misusing supposed-to-be-private members is one minor possibility amidst many challenges.

Re: C++ Patterns: The Badge

#109
post #92
post #60

Earlier quoted context omitted.

yeah, python LOC > 5000 try to debugging it while some dude just modified your type instance's guts.

OP's approach works if all dudes involved read the code before chaning it and stay off private parts even if they aren't guarded by the language constructs.

So it's an implicit contract based on syntax vs explicit?

It's a user/m_ prefix vs compiler/private. Im not sure if former is better. It's a strong trade off imho.

In my experience relying on people reading code and agreeing on imlicit contracts does not scale beyond 5 people, but maybe I've been mistreated by life.

Re: C++ Patterns: The Badge

#110
post #80

Earlier quoted context omitted.

There is no performance penalty in any modern compiler that I am aware of (effectively no code will be emitted). You can have a look here: https://godbolt.org/z/DmeYL-

Sure within a single compilation unit. Otherwise, I like dearrifling's suggestion.

The example also shows a call to a different translation unit. There's no code for passing the empty struct. There's also none for handling it, as you can see from the assembly output.

The one byte rule does nothing here, because its value is undefined and its address not observable.

edit: if you find a case where an empty struct parameter causes code to be emitted, let's consider filing bugs.

Post reply on HN