ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4CTCounter.hh
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4CTCounter.hh
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 //
27 // Author: Mathieu Karamitros
28 
29 /*
30  * Compile time counter to use flags with switch and add new flags
31  *
32  * - Usage 1
33  *
34  * class A {
35  * G4CT_COUNT_INIT(0)
36  * CT_COUNT(a)
37  * CT_COUNT(b)
38  * CT_COUNT(c)
39  * };
40  *
41  * class B1 : public A{
42  * CT_COUNT(d)
43  * };
44  *
45  * class B2 : public A{
46  * CT_COUNT(e)
47  * };
48  * class C : public B1{
49  * CT_COUNT(f)
50  * };
51  *
52  * Result
53  * a = 0
54  * b = 1
55  * c = 2
56  * d & e = 3
57  * f = 4
58  *
59  * - Usage 2
60  * namespace CounterNSpace{
61  * G4CT_COUNT_INIT(0)
62  * CT_COUNT(a)
63  * CT_COUNT(b)
64  * CT_COUNT(c)
65  * }
66  *
67  * // extend
68  * namespace CounterNSpace{
69  * CT_COUNT(d)
70  * CT_COUNT(e)
71  * CT_COUNT(f)
72  * }
73  */
74 
75 #ifndef G4CTCounter_h
76 #define G4CTCounter_h
77 
78 template<int N>
79 struct G4Number: public G4Number<N-1>{
80  static constexpr int value=N;
81 };
82 
83 template<>
84 struct G4Number<0>{
85  static constexpr int value=0;
86 };
87 
88 //------------------------------------------------------------------------------
89 
90 #define G4CT_COUNT_INIT(init_value) \
91  static constexpr G4Number<init_value> \
92  Counter(G4Number<init_value>) { \
93  return G4Number<init_value>(); \
94  }
95 
96 #define G4CT_COUNT(flagName) \
97  static constexpr const int flagName = \
98  decltype(Counter(G4Number<255>{}) )::value; \
99  static constexpr G4Number<flagName + 1> \
100  Counter(G4Number<flagName + 1>){ \
101  return G4Number<flagName +1 >{}; \
102  }
103 
104 //------------------------------------------------------------------------------
105 // On Win platforms, static functions must not be inlined, use the following
106 // macros to separate definition and implementation of static function
107 // to avoid potential crashes
108 
109 #define G4CT_COUNT_INIT_DEF(init_value) \
110  static constexpr G4Number<init_value> \
111  Counter(G4Number<init_value>);
112 
113 #define G4CT_COUNT_INIT_IMPL(enumName, init_value) \
114  constexpr G4Number<init_value> \
115  enumName::Counter(G4Number<init_value>){ \
116  return G4Number<init_value>{}; \
117  }
118 
119 #define G4CT_COUNT_DEF(flagName) \
120  static constexpr const int flagName = \
121  decltype(Counter(G4Number<255>{}))::value; \
122  static constexpr G4Number<flagName + 1> \
123  Counter(G4Number<flagName + 1>);
124 
125 #define G4CT_COUNT_IMPL(enumName, flagName) \
126  constexpr G4Number<enumName::flagName + 1> \
127  enumName::Counter(G4Number<enumName::flagName + 1>){ \
128  return G4Number<enumName::flagName +1 >{}; \
129  }
130 
131 //------------------------------------------------------------------------------
132 
133 #endif