nodereadimpl.h 1.89 KB
Newer Older
1
2
3
4
5
6
7
8
#pragma once

namespace YAML
{
	// implementation for Node::Read
	// (the goal is to call ConvertScalar if we can, and fall back to operator >> if not)
	// thanks to litb from stackoverflow.com
	// http://stackoverflow.com/questions/1386183/how-to-call-a-templated-function-if-it-exists-and-something-else-otherwise/1386390#1386390
9
10

	// Note: this doesn't work on gcc 3.2, but does on gcc 3.4 and above. I'm not sure about 3.3.
11
	
12
#if __GNUC__ && (__GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ <= 3))
13
14
15
16
17
18
19
20
	// trick doesn't work? Just fall back to ConvertScalar.
	// This means that we can't use any user-defined types as keys in a map
	template <typename T>
	inline bool Node::Read(T& value) const {
		return ConvertScalar(*this, value);
	}
#else
	// usual case: the trick!
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
	template<bool>
	struct read_impl;
	
	// ConvertScalar available
	template<>
	struct read_impl<true> {
		template<typename T>
		static bool read(const Node& node, T& value) {
			return ConvertScalar(node, value);
		}
	};

	// ConvertScalar not available
	template<>
	struct read_impl<false> {
		template<typename T>
		static bool read(const Node& node, T& value) {
			try {
				node >> value;
			} catch(const Exception&) {
				return false;
			}
			return true;
		}
	};
	
	namespace fallback {
		// sizeof > 1
		struct flag { char c[2]; };
		flag Convert(...);
		
52
		int operator,(flag, flag);
53
54
55
56
		
		template<typename T>
		void operator,(flag, T const&);
		
57
		char operator,(int, flag);
58
59
60
61
62
63
64
65
	}

	template <typename T>
	inline bool Node::Read(T& value) const {
		using namespace fallback;

		return read_impl<sizeof (fallback::flag(), Convert(std::string(), value), fallback::flag()) != 1>::read(*this, value);
	}
66
#endif // done with trick
67
68
69
70
71
72
73
74
75
76
77
	
	// the main conversion function
	template <typename T>
	inline bool ConvertScalar(const Node& node, T& value) {
		std::string scalar;
		if(!node.GetScalar(scalar))
			return false;
		
		return Convert(scalar, value);
	}
}