ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4AnyMethod.hh
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4AnyMethod.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 //
28 // See http://www.boost.org/libs/any for Documentation.
29 // Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved.
30 //
31 // Permission to use, copy, modify, and distribute this software for any
32 // purpose is hereby granted without fee, provided that this copyright and
33 // permissions notice appear in all copies and derivatives.
34 //
35 // This software is provided "as is" without express or implied warranty.
36 // What: variant At boost::any
37 // who: contributed by Kevlin Henney,
38 // with features contributed and bugs found by
39 // Ed Brey, Mark Rodgers, Peter Dimov, and James Curran
40 // when: July 2001
41 // where: tested with BCC 5.5, MSVC 6.0, and g++ 2.95
42 
43 #ifndef G4AnyMethod_h
44 #define G4AnyMethod_h 1
45 
46 
47 #include <functional>
48 
50 class G4BadArgument: public std::bad_cast {
51 public:
53  virtual const char* what() const throw() {
54  return "G4BadArgument: failed operator()";
55  }
56 };
57 
58 #if defined(G4USE_STD11) || defined(G4USE_STD14)
59  #include <type_traits>
60  using std::remove_reference;
61  using std::remove_const;
62 // original usage below in G4AnyMethod (pre C++11) was without namespace std::
63 // so if compiler has them, make them available without the namespace
64 #else
65 // these are the reference "possible implementations" of a C++11 feature
66 // c.f. http://en.cppreference.com/w/cpp/types/remove_reference
67 // but they clash badly with C++11 definitions supplied by the compiler
68 // so use them only if C++11 is not enabled or there is no possibility
69 // of clashing with the ones defined in std:: namespace
70 // (i.e. avoid "using namespace std")
71 template<typename T> struct remove_reference {typedef T type;};
72 template<typename T> struct remove_reference<T&> {typedef T type;};
73 template<typename T> struct remove_reference<const T&> {typedef T type;};
74 template<typename T> struct remove_const<const T> {typedef T type;};
75 #endif
76 
81 class G4AnyMethod {
82 public:
84  G4AnyMethod(): fContent(0), narg(0) {}
85  template <class S, class T> G4AnyMethod(S (T::*f)()) : narg(0) {
86  fContent = new FuncRef<S,T>(f);
87  }
88  template <class S, class T, class A0> G4AnyMethod(S (T::*f)(A0)) : narg(1) {
90  }
91  template <class S, class T, class A0, class A1> G4AnyMethod(S (T::*f)(A0,A1)) : narg(2) {
93  }
94  G4AnyMethod(const G4AnyMethod &other):
95  fContent(other.fContent ? other.fContent->Clone() : 0),narg(other.narg) {}
98  delete fContent;
99  }
100 
103  std::swap(narg, rhs.narg);
104  return *this;
105  }
107  template <class S, class T> G4AnyMethod& operator =(S (T::*f)()) {
108  G4AnyMethod(f).Swap(*this);
109  narg = 0;
110  return *this;
111  }
112  template <class S, class T, class A0> G4AnyMethod& operator =(S (T::*f)(A0)) {
113  G4AnyMethod(f).Swap(*this);
114  narg = 1;
115  return *this;
116  }
117  template <class S, class T, class A0, class A1> G4AnyMethod& operator =(S (T::*f)(A0, A1)) {
118  G4AnyMethod(f).Swap(*this);
119  narg = 1;
120  return *this;
121  }
124  G4AnyMethod(rhs).Swap(*this);
125  narg = rhs.narg;
126  return *this;
127  }
129  bool Empty() const {
130  return !fContent;
131  }
133  void operator()(void* obj) {
134  fContent->operator()(obj);
135  }
136  void operator()(void* obj, const std::string& a0) {
137  fContent->operator()(obj, a0);
138  }
140  size_t NArg() const { return narg; }
141 
142  const std::type_info& ArgType(size_t n = 0) const {
143  return fContent ? fContent->ArgType(n) : typeid(void);
144  }
145 
146 private:
147  class Placeholder {
148  public:
150  virtual ~Placeholder() {}
151  virtual Placeholder* Clone() const = 0;
152  virtual void operator()(void*) = 0;
153  virtual void operator()(void*,const std::string&) = 0;
154  virtual const std::type_info& ArgType(size_t) const = 0;
155  };
156 
157  template <class S, class T> struct FuncRef: public Placeholder {
158  FuncRef(S (T::*f)()) : fRef(f) {}
159 
160  virtual void operator()(void* obj) {
161  ((T*)obj->*fRef)();
162  }
163  virtual void operator()(void*, const std::string&) {
164  throw G4BadArgument();
165  }
166  virtual Placeholder* Clone() const {
167  return new FuncRef(fRef);
168  }
169  virtual const std::type_info& ArgType(size_t) const {
170  return typeid(void);
171  }
172  S (T::*fRef)();
173  };
174 
175  template <class S, class T, class A0> struct FuncRef1: public Placeholder {
176  typedef typename remove_const<typename remove_reference<A0>::type>::type nakedA0;
177 
178  FuncRef1(S (T::*f)(A0)) : fRef(f) {}
179 
180  virtual void operator()(void*) {
181  throw G4BadArgument();
182  }
183  virtual void operator()(void* obj, const std::string& s0) {
184  nakedA0 a0;
185  std::stringstream strs(s0);
186  strs >> a0;
187  ((T*)obj->*fRef)(a0);
188  }
189  virtual Placeholder* Clone() const {
190  return new FuncRef1(fRef);
191  }
192  virtual const std::type_info& ArgType(size_t) const {
193  return typeid(A0);
194  }
195  S (T::*fRef)(A0);
196  };
197 
198  template <class S, class T, class A0, class A1> struct FuncRef2: public Placeholder {
199  typedef typename remove_const<typename remove_reference<A0>::type>::type nakedA0;
200  typedef typename remove_const<typename remove_reference<A1>::type>::type nakedA1;
201 
202  FuncRef2(S (T::*f)(A0, A1)) : fRef(f) {}
203 
204  virtual void operator()(void*) {
205  throw G4BadArgument();
206  }
207  virtual void operator()(void* obj, const std::string& s0) {
208  nakedA0 a0;
209  nakedA1 a1;
210  std::stringstream strs(s0);
211  strs >> a0 >> a1;
212  ((T*)obj->*fRef)(a0, a1);
213  }
214  virtual Placeholder* Clone() const {
215  return new FuncRef2(fRef);
216  }
217  virtual const std::type_info& ArgType(size_t i) const {
218  return i == 0 ? typeid(A0) : typeid(A1);
219  }
220  S (T::*fRef)(A0, A1);
221  };
222 
224  size_t narg;
225 };
226 
227 #endif