Beman Project coding guidelines

I’m ready to contribute. So far, there isn’t much there to follow. It seems prudent to code according to an agreed set of guidelines to make the code reasonably consistent. Code layout (indentation, placement of curlies/parenthesis, West or East const) can reasonably be achieved using clang-format possibly with some specific setting (I’m not gonna like it but I could adhere to the defaults). So, that’s not what I’m talking about. However, here are some of the items which should probably be consistent:

  • Files should have a copyright. I know that Boost started off with personalized copyrights but eventually moved to one common Boost copyright. Probably the files for the Beman Project should have a Beman Project copyright although that isn’t a legal entity (yet?). That detail should be sorted out early on to avoid having to deal with copyright assignments later.
  • Names of source and header files, in particular their suffixes. The beman/example uses .hxx and .cxx.
  • Location of the files: the beman/example places the files into src/example next to each other. What structure is expected.
  • It may be nice to use modules for a freshly created C++ project. On the other hand, it seems module support still isn’t quite there according cppreference status. Should projects be structured in a way which would allow use as modules or use via headers depending on some deployment options? I’m not quite sure what that structure might be, though. I could imagine some code annotations in files which are picked up by a program to transform a header-based code based into mdules-based one.
  • What namespaces are the projects supposed to use?
    • Successful standard proposals will live in std. To replicate the intended final interaction, the code should probably, indeed, live in namespace std, at least, optionally. Sadly, namespace aliases can’t be used to open a namespace for definitions: otherwise there could be one local place for configurations defining the namespace without resorting to macros. As is, it seems we may need to resort to macros.
    • Unless modules are used, it will be necessary to hide names into specific namespaces to avoid ADL to accidentally find entities not intended to be found. How should the corresponding namespaces be named and where should they be located?
    • It would be great if tests could seamlessly test actual standard library code and Beman Project code. To that end it is probably necessary come up with a strategy referring to names in namespaces which can be somehow configured. Mostly that can probably be done using an agreed namespace alias referring to the namespace supposed to get into namespace std eventually.
  • Standard library code needs to uglify non-standard names, typically using reserved names like those starting with an underscore followed by a capital letter. Should Beman Project contributions also uglify names.
  • The files should probably be generally structured consistently and contain certain key parts:
    • All files should include a copyright notice and probably a license/pointer to a license. The exact text should probably be consistent boiler plate, adjusted for different files (e.g., source files and cmake files use different comments).
    • Header files should include guards against multiple inclusion. I’m not a fan of #pragma once and would rather use consistently named include guards.

There are likely many more details which should be agreed upon. Maybe the code should also adhere to the Core Guidelines or a subset thereof. Is there a checker for (a subset of) these guidelines and if so, can/should it be configured for Beman Project projects? Are there other guidelines which should be followed.

I’m quite certainly that I’ll come across various other aspects once I start working on an actual project.

2 Likes

Hi Dietmar -

Thanks for the questions. I’ve invited you to the Beman Project on Github where we had some earlier discussions were had that should probably be moved down here as FAQ. Let me try to address a few things:

Files should have a copyright. I know that Boost started off with personalized copyrights but eventually moved to one common Boost copyright.

We had a lot of conversation about licenses – our TLDR is that we’re recommending MIT by default for the moment, but really any of Boost, MIT, Apache with LLVM exception should be fine. Due to the nature of this being a federated project we expect different libraries to have different licenses.

  • Names of source and header files, in particular their suffixes. The beman/example uses .hxx and .cxx.
  • Location of the files: the beman/example places the files into src/example next to each other. What structure is expected.

There’s a draft idea here. I’ll reproduce the core here (I added examples at the top level because that’s where it normally is)

Subproject structure:

The Beman template should include:

/include
/src (if applicable)
/examples
/test
/doc
/paper
CMakeLists.txt

A sub-project should put its implementation in beman::cppN, where N is 26, 29,
etc. The N is the targeted ship vehicle for that subproject’s paper. For
each cppN namespace, a user will see “inline namespace cppN” when building in
C++N mode, and just “namespace cppN” otherwise. Sub-project authors are
encouraged but not required to also back-fill compatibility implementations
for cpp(N-3) and cpp(N-6) namespaces.

Standard library code needs to uglify non-standard names,

My take is no – because we’re mostly expecting the implementations to redo the impl – it’s mostly the tests, with mods, that we’d expect to reuse.

The files should probably be generally structured consistently and contain certain key parts:

Good points – we should add that. Maybe we should write a paper to standardize pragma once since I think all the compilers support it. We use it internally bc it’s easier.

Core guidelines

Probably a good idea lol – I think clang-tidy can check them – would be a good target for CI tooling.

That’s great to hear Dietmar! This is great stuff…

The Boost project has never required copyright assignment to the Boost Foundation. You can see relatively recent submissions have a copyright notice mentioning the author and a license notice.

The Beman project should follow suit by requiring a copyright and license notice in every file where the license is one of those approved for the project. I’ll try to put together a list of requirements this week by collecting the material from the work done at C++Now.

One of the values we agreed upon is tending toward industry consensus when it comes to tooling choices. We should do the same for questions like these. A GitHub search roughly indicates the relative popularity of header extensions.

*.hpp *.hxx *.hh
4.8M 348K 506K

Given these results, it seems like .hpp/.cpp should be preferred.

I don’t think the tooling is quite there yet and we do want people to kick the wheels of these libraries.

I agree this needs to be defined. Putting things in std is dangerous, especially when there is a good chance of naming conflicts with newer compilers.

Core guidelines are a good practice, but I think requiring their usage may be over constraining implementations. Are there any particular rules you think should be mandated?

Thanks for the response! With respect to copyright notice and license I’m likely happy with any choice made (I consider it unlikely that consensus moves towards (L)GPL which would raise concerns for me). I do recall that I used to hold the copyright for some bits of the filesystem library (a small subset of that was part of the seed for Boost) and that I was asked to assign the copyright to something else (I think it was Boost but I don’t recall).

One reason why an organizational copyright may be preferable is that it seems more suitable when there are multiple contributors. The original contributor may have created the file and copyright notice but isn’t necessarily the main contributor. A suitably linked contributors.md could list the individuals although git also identifies them.

I agree with .hpp/.cpp. I was surprised that the example project uses .hxx/.cxx. .cpp also better matches the proposed beman::cppXX namespaces.

With respect to guiidelines I recall that there were some efforts in WG21 to gather guideliness for the standard C++ library (I don’t know what happened to that). I don’t have specific guidelines in mind which should be enforced and those which come to my mind are unlikely to receive agreement. I mentioned the Core Guidelines because there seems to be general agreement and if it is constraining for the standard C++ library maybe there is a need for amendments.

#pragma once has enough problems when it hits the reality of actual networked filesystems, plus the problems of files really being available through multiple paths, that it is not going to get standardized. The bug lists are just too long on the existing implementations.

This is without getting into fun with necessary but non-standard features like include_next.

GitHub - steve-downey/view_maybe: Proof of concept of view_maybe and GitHub - steve-downey/optional_ref are probably good candidates, corresponding to P1255 and P2988.

They may need a little bit of work, e.g. the namespaces are smd rather than beman. The optional there, I think, currently only compiles with GCC 14, as it uses deducing this to eliminate a lot of redundancy. Have we thought mechanically about how to bring projects started outside into the project? It’s git so there’s a few ways, from moving orgs to a fresh import of cleaned sources.

There’s a wide variety of sources for papers, too. Have we talked about standardizing at least the build targets for turning .md, .bs, .org, .tex and what have you into a well formed paper that won’t get bounced out of the room?

Interesting – I’d never heard of such an issue, but good to know.

Stop it with your logic, reason and data :wink: For sure .hpp first – should have realized given that it’s the choice in Boost. We probably need to change the example project. And we should make it into an annotated template addressing some of Dietmar’s points.

1 Like

Boost has pretty clear license guidelines that actually will probably work Boost Library Requirements and Guidelines

1 Like

Indeed these are excellent – I’m going to start the list :slight_smile:

This is something we discussed, but I’m not sure how to address fully. I could see us do something were we start to ifdef out stuff that only works on certain compilers when compiling on one where it won’t work. It might be nice if the table that summarizes all the libraries discussed the requirements needed – compiler, platforms, etc.

So far we’re doing a fetch content:

It seems clear that won’t be enough of course in the end.

In an attempt to kick things off, I have created a start of a std::execution implementation at beman-execution. It can build and does some checking (but doesn’t actually contain any meaningful code, yet). The tooling is probably all wrong and some of the style is likely not to everybody’s taste either.

1 Like

Wow! The ambition is amazing – if only we can recruit some additional implementors…

It would be cool if the tooling devs @bretbrownjr and friends had a look and made PR’s as appropriate. Did you start from the example?

2 posts were split to a new topic: Any proposals that could use an implementation?

cxx/hxx → cpp/hpp: 🎨 change from cxx/hxx to cpp/hpp by dustingooding · Pull Request #10 · beman-project/example · GitHub

1 Like

IMO the libraries should be normal libraries with their own new names (like fmt or scnlib or spdlog). All entities (headers, namespaces, macros, etc.) should be prefixed with the name of the libraries.

Use of the std namespace should be limited to extension APIs like specializing std::hash.

I’m also skeptical of a shared top-level beman namespace and/or sub-namespaces per C++ version. There are a few scenarios where I could see this being an issue, but a straightforward one would be the case where the same program would link in one than more implementation of std::foobar, either via more than one beman implementation or via a beman implementation conflicting with an implementation of the standard library. It seems like a recipe for ODR and other tooling issues in my mind.

It should be interesting to be able to use at least some duplicate implementations side-by-side in the same link as well. This could be to allow seamless deprecation workflows or apples-to-apples comparisons between implementations.

It’s possible (though maybe not advisable?) to reopen the std namespace and pull the names in a from the foobar library into it if that’s essential for some reason.

I’ve thought but haven’t written any code yet.

I’m hoping we can provide at least all of FetchContent, Conan, and vcpkg workflows via the beman repo. I believe we could move the repo enrollment out of the CMakeLists.txt and into a JSON file that should be fairly obvious to add entries to. If it includes both pinning information (i.e. git commits and/or tags) and default branch info (i.e. main or master or trunk), we should be able to support both bleeding edge and stable workflows.

I believe we can use conanfiles in the beman repo and a vcpkg overlay as well, though that is just an educated guess at this point. I would really like to keep all dependency management information out of each beman library. I think we should plan on scaling at least to dozens of repos, and especially if we expect to incorporate many of them from outside the beman-project org, we should plan on relatively little ability to “sneak” in to each repo and fix tooling and packaging details in a timely manner. I would rather keep as much of that sort of thing separate from the libraries themselves.

Of course, I’m a realist about this, especially in the short term, but let’s keep asking ourselves “do I want to maintain 40 instances of this logic copy/pasted around?” every time we think about enhancing the example repo and eventually the repo template. Cattle, not pets, please.

I think there’s going to have to be a few things imposed on the target libraries. In particular I’m thinking about header includes and namespaces. I don’t see how we get around asking authors to conform to some standard so that users could rely on something like #include and using beman::cpp23. The only other way to do that is to have this part be in the beman project proper – but for a big library that might be a lot of work (@dietmarkuehl mentioned that this has led to a lot of work on some projects he’s been involved with).

Would this not manifest as pull requests to the repo’s themselves? Also if we have a ‘slow uptake’ from the primary author I think we could maintain our own clone for a bit?

Yes, but I would expect that to add up to hundreds of PRs spread out over however many repos. Compare that to putting all the dependency management PRs in one place. I expect the latter will be more sustainable, but it’s not the only way to go.

Yeah, we could maintain a fork in beman-project if need be. If that turns out to be fairly ergonomic, possibly that’s exactly the way we incorporate that sort of project.

A post was split to a new topic: Beman template directory structure