nodereadimpl.h 1.43 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#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
	
	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(...);
		
41
		int operator,(flag, flag);
42
43
44
45
		
		template<typename T>
		void operator,(flag, T const&);
		
46
		char operator,(int, flag);
47
48
49
50
51
52
53
54
55
56
57
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);
	}
	
	// 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);
	}
}