1 #ifndef NODEREADIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 2 #define NODEREADIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 3 4 #if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 5 #pragma once 6 #endif 7 8 9 namespace YODA_YAML 10 { 11 // implementation for Node::Read 12 // (the goal is to call ConvertScalar if we can, and fall back to operator >> if not) 13 // thanks to litb from stackoverflow.com 14 // http://stackoverflow.com/questions/1386183/how-to-call-a-templated-function-if-it-exists-and-something-else-otherwise/1386390#1386390 15 16 // Note: this doesn't work on gcc 3.2, but does on gcc 3.4 and above. I'm not sure about 3.3. 17 18 #if __GNUC__ && (__GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ <= 3)) 19 // trick doesn't work? Just fall back to ConvertScalar. 20 // This means that we can't use any user-defined types as keys in a map 21 template <typename T> Read(T & value)22 inline bool Node::Read(T& value) const { 23 return ConvertScalar(*this, value); 24 } 25 #else 26 // usual case: the trick! 27 template<bool> 28 struct read_impl; 29 30 // ConvertScalar available 31 template<> 32 struct read_impl<true> { 33 template<typename T> 34 static bool read(const Node& node, T& value) { 35 return ConvertScalar(node, value); 36 } 37 }; 38 39 // ConvertScalar not available 40 template<> 41 struct read_impl<false> { 42 template<typename T> 43 static bool read(const Node& node, T& value) { 44 try { 45 node >> value; 46 } catch(const Exception&) { 47 return false; 48 } 49 return true; 50 } 51 }; 52 53 namespace fallback { 54 // sizeof > 1 55 struct flag { char c[2]; }; 56 flag Convert(...); 57 58 int operator,(flag, flag); 59 60 template<typename T> 61 char operator,(flag, T const&); 62 63 char operator,(int, flag); 64 int operator,(char, flag); 65 } 66 67 template <typename T> 68 inline bool Node::Read(T& value) const { 69 using namespace fallback; 70 71 return read_impl<sizeof (fallback::flag(), Convert(std::string(), value), fallback::flag()) != 1>::read(*this, value); 72 } 73 #endif // done with trick 74 75 // the main conversion function 76 template <typename T> ConvertScalar(const Node & node,T & value)77 inline bool ConvertScalar(const Node& node, T& value) { 78 std::string scalar; 79 if(!node.GetScalar(scalar)) 80 return false; 81 82 return Convert(scalar, value); 83 } 84 } 85 86 #endif // NODEREADIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 87