Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create FairBaseTypes.h #1410

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open

Conversation

karabowi
Copy link
Collaborator

Created namespace FairRoot
with struct EntryID {size_t fId;}.

Should replace PR #1405.


Checklist:

Copy link
Member

@ChristianTackeGSI ChristianTackeGSI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this!

Here is a first set of comments to improve some parts.

}

private:
underlying_type fId;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use default member initializers:

Suggested change
underlying_type fId;
underlying_type fId{std::numeric_limits<underlying_type>::max()};


EntryID(underlying_type value) : fId(value) {}

EntryID() : EntryID(None) {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which simplifies the default constructor a lot.

Suggested change
EntryID() : EntryID(None) {}
EntryID() = default;

struct EntryID {
using underlying_type = size_t;

static constexpr underlying_type None = std::numeric_limits<underlying_type>::max();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice, if None would be of type EntryID, right?

Suggested change
static constexpr underlying_type None = std::numeric_limits<underlying_type>::max();
static const EntryID None;

And add this after the closing } of the class, but inside the namespace:

/// \sa https://stackoverflow.com/questions/29432283/c-static-constexpr-field-with-incomplete-type/50295183#50295183
inline constexpr const EntryID EntryID::None{};


namespace FairRoot {
struct EntryID {
using underlying_type = size_t;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like size_t.

If you intend to use EntryId as a member of a class that gets written to a ROOT file, you should consider using an integer with a fixed size, maybe uint32_t or uint64_t, or even some of the ROOT types.

If on the other hand, EntryID is strictly for runtime only use, then size_t is fine.

Copy link
Member

@ChristianTackeGSI ChristianTackeGSI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first iteration of the Doxygen docs for the namespace is here. And the link to the current Doxygen build for this PR can be found here: https://github.com/FairRootGroup/FairRoot/pull/1410/checks (and click on Doxygen-Preview).

Comment on lines 21 to 22
namespace FairRoot {
struct EntryID {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider to add some Doxygen comments to the namespace and class?

Suggested change
namespace FairRoot {
struct EntryID {
/**
* \brief Main namespace for FairRoot classes / types
*
* All new public classes and types of FairRoot will be in this namespace.
* Note: Nost classes are still in no namespace.
*/
namespace FairRoot {
/**
* \brief <What Entry is this ID meant for?>
*/
struct EntryID
{

Created `namespace FairRoot`
with `struct EntryID {size_t fId;}`.

Should replace PR FairRootGroup#1405.
* All new public classes and types of FairRoot will be in this namespace.
* Note: Nost classes are still in no namespace.
*/
namespace FairRoot {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't we agree on a lowercase name for this?

Suggested change
namespace FairRoot {
namespace fairroot {

If we didn't, I would still suggest to use lowercase. Checking the guidelines of Mozilla (upon which we base our clang-format), they seem to suggest lowercase: https://firefox-source-docs.mozilla.org/code-quality/coding-style/coding_style_cpp.html#c-namespaces

So do the Alice guidelines: https://rawgit.com/AliceO2Group/CodingGuidelines/master/naming_formatting.html?showone=Namespace_Names#Namespace_Names

For me it's more a personal preference. But one objective reason could be so they are distinguishable from class names.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, I will change it.

@rbx
Copy link
Member

rbx commented Jun 20, 2023

Soooo, what are the benefits of going full type here?

What do we loose with a simpler:

namespace fairroot
{
using EntryID = size_t;
}

* \brief Main namespace for FairRoot classes / types
*
* All new public classes and types of FairRoot will be in this namespace.
* Note: Nost classes are still in no namespace.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Note: Nost classes are still in no namespace.
* Note: Most classes are still in no namespace.

@dennisklein
Copy link
Member

dennisklein commented Jun 20, 2023

Soooo, what are the benefits of going full type here?

I guess, the idea would be to have safer-to-use and better-self-documenting function signatures (and call sites), e.g.

void RunReco(EntryID start, EntryID stop); // range [start, stop]
void RunReco(EntryID start, int n);        // range [start, start + n]
void RunReco(EntryID id);                  // single entry
void RunReco(int n);                       // n entries (starting from some implicit cursor)

With an alias it would be less clear what is meant and the compiler couldn't help you, if you misuse one of the signatures. (some overloads wouldn't even be possible). Now imagine argument lists with even more int args, where some are timeouts in seconds, different ids etc, easy to mess up the order when calling.

@dennisklein
Copy link
Member

dennisklein commented Jun 20, 2023

@rbx But I am not 100% convinced myself, if this is the best use case for a "strong alias". Especially, as there is already existing code using all kinds of int, uint, size_t etc for the same thing including serialized root files that need to be read back etc. Not sure, how much will break for the good or the worse^^

/**Run for the given single entry*/
void Run(Long64_t entry);
/**Run event reconstruction from event number NStart to event number NStop */
void RunEventReco(Int_t NStart, Int_t NStop);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we also should deprecated the int, int overloads first before removing them, right?

Replaced `Int_t` with the new type `EntryID`
in `FairRun` and derived classes.

Depracated `void FairRunAna::Run(Long64_t entry)`,
which internally calls introduced `void RunSingle(FairRoot::EntryID entry);`.
@dennisklein
Copy link
Member

If we see a potential for more "strong aliases" like this one in the near future, we could adopt the templates proposed here: https://www.foonathan.net/2016/10/strong-typedefs/

@karabowi
Copy link
Collaborator Author

Soooo, what are the benefits of going full type here?

I guess, the idea would be to have safer-to-use and better-self-documenting function signatures (and call sites), e.g.

void RunReco(EntryID start, EntryID stop); // range [start, stop]
void RunReco(EntryID start, int n);        // range [start, start + n]
void RunReco(EntryID id);                  // single entry
void RunReco(int n);                       // n entries (starting from some implicit cursor)

With an alias it would be less clear what is meant and the compiler couldn't help you, if you misuse one of the signatures. (some overloads wouldn't even be possible). Now imagine argument lists with even more int args, where some are timeouts in seconds, different ids etc, easy to mess up the order when calling.

Are you also proposing to ultimately replace the Run() functions with RunReco()?

@dennisklein
Copy link
Member

Soooo, what are the benefits of going full type here?

I guess, the idea would be to have safer-to-use and better-self-documenting function signatures (and call sites), e.g.

void RunReco(EntryID start, EntryID stop); // range [start, stop]
void RunReco(EntryID start, int n);        // range [start, start + n]
void RunReco(EntryID id);                  // single entry
void RunReco(int n);                       // n entries (starting from some implicit cursor)

With an alias it would be less clear what is meant and the compiler couldn't help you, if you misuse one of the signatures. (some overloads wouldn't even be possible). Now imagine argument lists with even more int args, where some are timeouts in seconds, different ids etc, easy to mess up the order when calling.

Are you also proposing to ultimately replace the Run() functions with RunReco()?

? I cannot follow

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants