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