Geant4 Cross Reference |
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 // G4AnyMethod 27 // 28 // Class description: 29 // 30 // The G4AnyMethod class represents any object method. 31 // The class only holds a member pointer. 32 33 // See http://www.boost.org/libs/any for Documentation. 34 // Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved. 35 // 36 // Permission to use, copy, modify, and distribute this software for any 37 // purpose is hereby granted without fee, provided that this copyright and 38 // permissions notice appear in all copies and derivatives. 39 // 40 // This software is provided "as is" without express or implied warranty. 41 // What: variant At boost::any 42 // who: contributed by Kevlin Henney, 43 // with features contributed and bugs found by 44 // Ed Brey, Mark Rodgers, Peter Dimov, and James Curran 45 // when: July 2001 46 // -------------------------------------------------------------------- 47 #ifndef G4AnyMethod_hh 48 #define G4AnyMethod_hh 1 49 50 #include "G4Types.hh" 51 52 #include <functional> 53 #include <sstream> 54 #include <type_traits> 55 56 /** Bad Argument exception */ 57 class G4BadArgument : public std::bad_cast 58 { 59 public: 60 G4BadArgument() = default; 61 const char* what() const throw() override { return "G4BadArgument: failed operator()"; } 62 }; 63 64 class G4AnyMethod 65 { 66 public: 67 G4AnyMethod() = default; 68 69 template<class S, class T> 70 G4AnyMethod(S (T::*f)()) 71 { 72 fContent = new FuncRef<S, T>(f); 73 } 74 75 template<class S, class T, class A0> 76 G4AnyMethod(S (T::*f)(A0)) : narg(1) 77 { 78 fContent = new FuncRef1<S, T, A0>(f); 79 } 80 81 template<class S, class T, class A0, class A1> 82 G4AnyMethod(S (T::*f)(A0, A1)) : narg(2) 83 { 84 fContent = new FuncRef2<S, T, A0, A1>(f); 85 } 86 87 G4AnyMethod(const G4AnyMethod& other) 88 : fContent(other.fContent != nullptr ? other.fContent->Clone() : nullptr), narg(other.narg) 89 {} 90 91 ~G4AnyMethod() { delete fContent; } 92 93 G4AnyMethod& Swap(G4AnyMethod& rhs) 94 { 95 std::swap(fContent, rhs.fContent); 96 std::swap(narg, rhs.narg); 97 return *this; 98 } 99 100 template<class S, class T> 101 G4AnyMethod& operator=(S (T::*f)()) 102 { 103 G4AnyMethod(f).Swap(*this); 104 narg = 0; 105 return *this; 106 } 107 108 template<class S, class T, class A0> 109 G4AnyMethod& operator=(S (T::*f)(A0)) 110 { 111 G4AnyMethod(f).Swap(*this); 112 narg = 1; 113 return *this; 114 } 115 template<class S, class T, class A0, class A1> 116 G4AnyMethod& operator=(S (T::*f)(A0, A1)) 117 { 118 G4AnyMethod(f).Swap(*this); 119 narg = 1; 120 return *this; 121 } 122 123 G4AnyMethod& operator=(const G4AnyMethod& rhs) 124 { 125 G4AnyMethod(rhs).Swap(*this); 126 narg = rhs.narg; 127 return *this; 128 } 129 130 /** Query */ 131 132 G4bool Empty() const { return fContent == nullptr; } 133 134 /** call operators */ 135 136 void operator()(void* obj) { fContent->operator()(obj); } 137 void operator()(void* obj, const std::string& a0) { fContent->operator()(obj, a0); } 138 139 /** Number of arguments */ 140 141 std::size_t NArg() const { return narg; } 142 143 const std::type_info& ArgType(size_t n = 0) const 144 { 145 return fContent != nullptr ? fContent->ArgType(n) : typeid(void); 146 } 147 148 private: 149 class Placeholder 150 { 151 public: 152 Placeholder() = default; 153 virtual ~Placeholder() = default; 154 virtual Placeholder* Clone() const = 0; 155 virtual void operator()(void*) = 0; 156 virtual void operator()(void*, const std::string&) = 0; 157 virtual const std::type_info& ArgType(size_t) const = 0; 158 }; 159 160 template<class S, class T> 161 struct FuncRef : public Placeholder 162 { 163 FuncRef(S (T::*f)()) : fRef(f) {} 164 165 void operator()(void* obj) override { ((T*)obj->*fRef)(); } 166 void operator()(void*, const std::string&) override { throw G4BadArgument(); } 167 Placeholder* Clone() const override { return new FuncRef(fRef); } 168 const std::type_info& ArgType(std::size_t) const override { return typeid(void); } 169 S (T::*fRef)(); 170 }; 171 172 template<class S, class T, class A0> 173 struct FuncRef1 : public Placeholder 174 { 175 using nakedA0 = std::remove_const_t<std::remove_reference_t<A0>>; 176 177 FuncRef1(S (T::*f)(A0)) : fRef(f) {} 178 179 void operator()(void*) override { throw G4BadArgument(); } 180 void operator()(void* obj, const std::string& s0) override 181 { 182 nakedA0 a0; 183 std::stringstream strs(s0); 184 strs >> a0; 185 ((T*)obj->*fRef)(a0); 186 } 187 Placeholder* Clone() const override { return new FuncRef1(fRef); } 188 const std::type_info& ArgType(size_t) const override { return typeid(A0); } 189 S (T::*fRef)(A0); 190 }; 191 192 template<class S, class T, class A0, class A1> 193 struct FuncRef2 : public Placeholder 194 { 195 using nakedA0 = std::remove_const_t<std::remove_reference_t<A0>>; 196 using nakedA1 = std::remove_const_t<std::remove_reference_t<A1>>; 197 198 FuncRef2(S (T::*f)(A0, A1)) : fRef(f) {} 199 200 void operator()(void*) override { throw G4BadArgument(); } 201 void operator()(void* obj, const std::string& s0) override 202 { 203 nakedA0 a0; 204 nakedA1 a1; 205 std::stringstream strs(s0); 206 strs >> a0 >> a1; 207 ((T*)obj->*fRef)(a0, a1); 208 } 209 Placeholder* Clone() const override { return new FuncRef2(fRef); } 210 const std::type_info& ArgType(size_t i) const override 211 { 212 return i == 0 ? typeid(A0) : typeid(A1); 213 } 214 S (T::*fRef)(A0, A1); 215 }; 216 217 Placeholder* fContent = nullptr; 218 std::size_t narg = 0; 219 }; 220 221 #endif 222