C++11 for STAR.comments

P { margin-bottom: 0.08in; }CODE.cjk { font-family: "AR PL UMing HK",monospace; }CODE.ctl { font-family: "Lohit Devanagari",monospace; }A:link { }

PRE.cjk { font-family: "AR PL UMing HK",monospace; }PRE.ctl { font-family: "Lohit Devanagari",monospace; }H3 { margin-bottom: 0.08in; }H3.cjk { font-family: "AR PL UMing HK"; }H3.ctl { font-family: "Lohit Devanagari"; }P { margin-bottom: 0.08in; }CODE.cjk { font-family: "AR PL UMing HK",monospace; }CODE.ctl { font-family: "Lohit Devanagari",monospace; }A:link { }

>---------------------------------------------------------------------------------------------------------------------------

> As a general rule, put function definitions into the .cxx file and let the compiler decide what gets

> inlined (it can decide anyway, regardless of the inline keyword).

 

Generally I agree. But you mentioned “ let the compiler decide” which is not clear.

If user used package A and

in A.h int foo();

in A.cxx int foo(){return 0;}

 

Then user calls foo()

How compiler could do inline if it does not know where is the definition of foo()

Especially in the case where package A in library.

 

Additionally , when function is defined in .h file, gdb usually can not see it and can not set break.

So for debugging to put function into .cxx is good.

 

>---------------------------------------------------------------------------------------------------------------------------

>Decision: Avoid the use ROOT definitions of built-in data types and use the built-in C++ types

> Use int instead Int_t, float instead of Float_t, double instead of Double_t, etc.

But with exception:

Double32_t Double 8 bytes in memory, written as a 4 bytes float

Float16_t Float 4 bytes written with a truncated mantissa


 

>---------------------------------------------------------------------------------------------------------------------------

> Avoid using smart pointers in STAR code.

I agree with it. But inSTAR code a lot of classes have no relation to ROOT.

For these ones, probably smart pointers could be allowed.

 

 

 

>---------------------------------------------------------------------------------------------------------------------------

> When the logic of a program guarantees that a given instance of a base class is in fact an instance

> of a particular derived class, then use of a dynamic_cast or static_cast as an alternative

> may be also justified in such situations.

Note: Using dynamic_cast with classes without virtual function is senseless. It is impossible

recognize type of class in this case and dynamic_cast ==> static_cast

 

>---------------------------------------------------------------------------------------------------------------------------

> Prefer the prefix form of the increment (++i) and decrement (--i)

> operators because it has simpler semantics.

But user should remember that lines:

a = ++i;

and:

a = i++;

give different value of a.

 

>---------------------------------------------------------------------------------------------------------------------------

> Loops and Switch Statements.

> default: {
> assert(false);

Agree. It was discussion to use assert() here or not.

Wrong case means that code is completely wrong.

We can use return with error condition. Why it is not good.

1. Using error flag is not easy to implement if it is deep in code

2. Using exceptions also not good(see exceptions);

3. If we succeed to reach maker and then return StErr, most of

makers have no right to stop production. Then after many CPU days

we will produce wrong data, which we need to reprocess. Even that

will happen if somebody will look in the log file.

4. In the case of assert to find the bug is much easier.

 

 

========================================================================
OLD PART
========================================================================

> Each header file should contain only one or related class declarations for maintainability and for

> easier retrieval of class definitions.

 

It is not always good. Classes which are closely related with each other, are better to place together.

Like class of track parameters and class of parameter errors. Huge amount of small different files

is not manageable.

 

> Static variables in functions (called "function-local static variables" in the C++ terminology) are

> expensive and need care on destruction. Prefer to use static class variables where possible.

 

How they could be “expensive”? There is a lot of cases when they are convenient.

1. static int nCall = 0; nCall++; //counting the number of calls

2. static const double kQQQ = fun1(123.)*fun2(11.11)*sin(P_PI/3); // this constant calculated only once

3. the same especially important with arrays which must be calculated only once

4. static KONST* myk = KONST::instantiate(); // You can use once calculated pointer

But I agree, that using static variables for calculation is a bad idea. Especially if we will decide to use

threads.

 

> When using inheritance, make it public and declare overridden methods as override or final.

I think that using “final” for STAR is not too good. In any physical experiment, software is changing

all the time. To decide that class or method is final is not realistic.

 

> Use multiple inheritance implementation only when at most one of the base classes has an

> implementation; all other base classes must be pure interface classes.

Even more, it is better to avoid multiple inheritance at all.

 

 

> If a class was designed as a pure interface, keep it as a pure interface.

Not clear at all.

“If a class was designed as a pure interface, keep it as a pure interface”

“If a class was NOT designed as a pure interface, keep it as NOT a pure interface”????

 

 

 

> Hide internals. Avoid returning handles to internal data managed by your class.

It is true, with exception of pointer to to evident array.

For instance:

double xyz[3];

xyz[0] = A.x()

xyz[1] = A.x()

xyz[2] = A.x()

 

is not too convenient. Better is:

const double *XYZ = A.X();

 

> Prefer the use of fundamental types built-in C++ over ROOT types, except where

> absolutely required.

 

True, ROOT types like Double_t should be used only for persistent data members, to avoid problems with I/O between different machines

 

 

>Use C++ exceptions instead of return codes for error handling. Do not use exceptions to return values.

>Exceptions should be used for error handling

In C++ lectures, lecturer told to avoid exceptions as much as possible. Especially for error handling.

When exception is occurred stack is decreased and some destructors are called. During that, especially

during error handling, some other exceptions happened. As a result all the memory is destroyed and

extremely hard to find the bug.

 

> Avoid magic numbers (hard coded numbers).

True, but there are exceptions of this rule. For instance:

double xyz[3]; // where 3 is 3 dimensional space.

 

Case with:

enum {N=3}

double xyz[N];

gives the wrong impression that N could be non 3

 

> Prefer small and focused functions.

 

Yes and No. If you have 300 small functions which are called each others, then code is unreadable and slow.

 

> In general, avoid designs that require casting. You may use static_cast when necessary, but

> avoid const_cast and reinterpret_cast. C-casts are forbidden.

 

C-cast has the same behavior as static_cast

but expression:

(int*)p;

is less ugly and shorter than :

static_cast<int*>(p)