]> git.sesse.net Git - casparcg/blob - dependencies/boost/boost/property_tree/detail/ptree_implementation.hpp
Manually merged pull request #222
[casparcg] / dependencies / boost / boost / property_tree / detail / ptree_implementation.hpp
1 // ----------------------------------------------------------------------------
2 // Copyright (C) 2002-2006 Marcin Kalicinski
3 // Copyright (C) 2009 Sebastian Redl
4 //
5 // Distributed under the Boost Software License, Version 1.0.
6 // (See accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
8 //
9 // For more information, see www.boost.org
10 // ----------------------------------------------------------------------------
11 #ifndef BOOST_PROPERTY_TREE_DETAIL_PTREE_IMPLEMENTATION_HPP_INCLUDED
12 #define BOOST_PROPERTY_TREE_DETAIL_PTREE_IMPLEMENTATION_HPP_INCLUDED
13
14 #include <boost/iterator/iterator_adaptor.hpp>
15 #include <boost/iterator/reverse_iterator.hpp>
16 #include <boost/assert.hpp>
17 #include <memory>
18
19 #if defined(BOOST_MSVC) && \
20     (_MSC_FULL_VER >= 160000000 && _MSC_FULL_VER < 170000000)
21 #define BOOST_PROPERTY_TREE_PAIR_BUG
22 #endif
23
24 namespace boost { namespace property_tree
25 {
26     template <class K, class D, class C>
27     struct basic_ptree<K, D, C>::subs
28     {
29         struct by_name {};
30         // The actual child container.
31 #if defined(BOOST_PROPERTY_TREE_PAIR_BUG)
32         // MSVC 10 has moved std::pair's members to a base
33         // class. Unfortunately this does break the interface.
34         BOOST_STATIC_CONSTANT(unsigned,
35             first_offset = offsetof(value_type, first));
36         typedef multi_index_container<value_type,
37             multi_index::indexed_by<
38                 multi_index::sequenced<>,
39                 multi_index::ordered_non_unique<multi_index::tag<by_name>,
40                     multi_index::member_offset<value_type, const key_type,
41                                         first_offset>,
42                     key_compare
43                 >
44             >
45         > base_container;
46 #else
47         typedef multi_index_container<value_type,
48             multi_index::indexed_by<
49                 multi_index::sequenced<>,
50                 multi_index::ordered_non_unique<multi_index::tag<by_name>,
51                     multi_index::member<value_type, const key_type,
52                                         &value_type::first>,
53                     key_compare
54                 >
55             >
56         > base_container;
57 #endif
58         // The by-name lookup index.
59         typedef typename base_container::template index<by_name>::type
60             by_name_index;
61
62         // Access functions for getting to the children of a tree.
63         static base_container& ch(self_type *s) {
64             return *static_cast<base_container*>(s->m_children);
65         }
66         static const base_container& ch(const self_type *s) {
67             return *static_cast<const base_container*>(s->m_children);
68         }
69         static by_name_index& assoc(self_type *s) {
70             return ch(s).BOOST_NESTED_TEMPLATE get<by_name>();
71         }
72         static const by_name_index& assoc(const self_type *s) {
73             return ch(s).BOOST_NESTED_TEMPLATE get<by_name>();
74         }
75     };
76     template <class K, class D, class C>
77     class basic_ptree<K, D, C>::iterator : public boost::iterator_adaptor<
78         iterator, typename subs::base_container::iterator, value_type>
79     {
80         friend class boost::iterator_core_access;
81         typedef boost::iterator_adaptor<
82             iterator, typename subs::base_container::iterator, value_type>
83             baset;
84     public:
85         typedef typename baset::reference reference;
86         iterator() {}
87         explicit iterator(typename iterator::base_type b)
88             : iterator::iterator_adaptor_(b)
89         {}
90         reference dereference() const
91         {
92             // multi_index doesn't allow modification of its values, because
93             // indexes could sort by anything, and modification screws that up.
94             // However, we only sort by the key, and it's protected against
95             // modification in the value_type, so this const_cast is safe.
96             return const_cast<reference>(*this->base_reference());
97         }
98     };
99     template <class K, class D, class C>
100     class basic_ptree<K, D, C>::const_iterator : public boost::iterator_adaptor<
101         const_iterator, typename subs::base_container::const_iterator>
102     {
103     public:
104         const_iterator() {}
105         explicit const_iterator(typename const_iterator::base_type b)
106             : const_iterator::iterator_adaptor_(b)
107         {}
108         const_iterator(iterator b)
109             : const_iterator::iterator_adaptor_(b.base())
110         {}
111     };
112     template <class K, class D, class C>
113     class basic_ptree<K, D, C>::reverse_iterator
114         : public boost::reverse_iterator<iterator>
115     {
116     public:
117         reverse_iterator() {}
118         explicit reverse_iterator(iterator b)
119             : boost::reverse_iterator<iterator>(b)
120         {}
121     };
122     template <class K, class D, class C>
123     class basic_ptree<K, D, C>::const_reverse_iterator
124         : public boost::reverse_iterator<const_iterator>
125     {
126     public:
127         const_reverse_iterator() {}
128         explicit const_reverse_iterator(const_iterator b)
129             : boost::reverse_iterator<const_iterator>(b)
130         {}
131         const_reverse_iterator(
132             typename basic_ptree<K, D, C>::reverse_iterator b)
133             : boost::reverse_iterator<const_iterator>(b)
134         {}
135     };
136     template <class K, class D, class C>
137     class basic_ptree<K, D, C>::assoc_iterator
138         : public boost::iterator_adaptor<assoc_iterator,
139                                          typename subs::by_name_index::iterator,
140                                          value_type>
141     {
142         friend class boost::iterator_core_access;
143         typedef boost::iterator_adaptor<assoc_iterator,
144                                          typename subs::by_name_index::iterator,
145                                          value_type>
146             baset;
147     public:
148         typedef typename baset::reference reference;
149         assoc_iterator() {}
150         explicit assoc_iterator(typename assoc_iterator::base_type b)
151             : assoc_iterator::iterator_adaptor_(b)
152         {}
153         reference dereference() const
154         {
155             return const_cast<reference>(*this->base_reference());
156         }
157     };
158     template <class K, class D, class C>
159     class basic_ptree<K, D, C>::const_assoc_iterator
160         : public boost::iterator_adaptor<const_assoc_iterator,
161                                    typename subs::by_name_index::const_iterator>
162     {
163     public:
164         const_assoc_iterator() {}
165         explicit const_assoc_iterator(
166             typename const_assoc_iterator::base_type b)
167             : const_assoc_iterator::iterator_adaptor_(b)
168         {}
169         const_assoc_iterator(assoc_iterator b)
170             : const_assoc_iterator::iterator_adaptor_(b.base())
171         {}
172     };
173
174
175     // Big five
176
177     // Perhaps the children collection could be created on-demand only, to
178     // reduce heap traffic. But that's a lot more work to implement.
179
180     template<class K, class D, class C> inline
181     basic_ptree<K, D, C>::basic_ptree()
182         : m_children(new typename subs::base_container)
183     {
184     }
185
186     template<class K, class D, class C> inline
187     basic_ptree<K, D, C>::basic_ptree(const data_type &d)
188         : m_data(d), m_children(new typename subs::base_container)
189     {
190     }
191
192     template<class K, class D, class C> inline
193     basic_ptree<K, D, C>::basic_ptree(const basic_ptree<K, D, C> &rhs)
194         : m_data(rhs.m_data),
195           m_children(new typename subs::base_container(subs::ch(&rhs)))
196     {
197     }
198
199     template<class K, class D, class C>
200     basic_ptree<K, D, C> &
201         basic_ptree<K, D, C>::operator =(const basic_ptree<K, D, C> &rhs)
202     {
203         self_type(rhs).swap(*this);
204         return *this;
205     }
206
207     template<class K, class D, class C>
208     basic_ptree<K, D, C>::~basic_ptree()
209     {
210         delete &subs::ch(this);
211     }
212
213     template<class K, class D, class C> inline
214     void basic_ptree<K, D, C>::swap(basic_ptree<K, D, C> &rhs)
215     {
216         m_data.swap(rhs.m_data);
217         // Void pointers, no ADL necessary
218         std::swap(m_children, rhs.m_children);
219     }
220
221     // Container view
222
223     template<class K, class D, class C> inline
224     typename basic_ptree<K, D, C>::size_type
225         basic_ptree<K, D, C>::size() const
226     {
227         return subs::ch(this).size();
228     }
229
230     template<class K, class D, class C> inline
231     typename basic_ptree<K, D, C>::size_type
232         basic_ptree<K, D, C>::max_size() const
233     {
234         return subs::ch(this).max_size();
235     }
236
237     template<class K, class D, class C> inline
238     bool basic_ptree<K, D, C>::empty() const
239     {
240         return subs::ch(this).empty();
241     }
242
243     template<class K, class D, class C> inline
244     typename basic_ptree<K, D, C>::iterator
245         basic_ptree<K, D, C>::begin()
246     {
247         return iterator(subs::ch(this).begin());
248     }
249
250     template<class K, class D, class C> inline
251     typename basic_ptree<K, D, C>::const_iterator
252         basic_ptree<K, D, C>::begin() const
253     {
254         return const_iterator(subs::ch(this).begin());
255     }
256
257     template<class K, class D, class C> inline
258     typename basic_ptree<K, D, C>::iterator
259         basic_ptree<K, D, C>::end()
260     {
261         return iterator(subs::ch(this).end());
262     }
263
264     template<class K, class D, class C> inline
265     typename basic_ptree<K, D, C>::const_iterator
266         basic_ptree<K, D, C>::end() const
267     {
268         return const_iterator(subs::ch(this).end());
269     }
270
271     template<class K, class D, class C> inline
272     typename basic_ptree<K, D, C>::reverse_iterator
273         basic_ptree<K, D, C>::rbegin()
274     {
275         return reverse_iterator(this->end());
276     }
277
278     template<class K, class D, class C> inline
279     typename basic_ptree<K, D, C>::const_reverse_iterator
280         basic_ptree<K, D, C>::rbegin() const
281     {
282         return const_reverse_iterator(this->end());
283     }
284
285     template<class K, class D, class C> inline
286     typename basic_ptree<K, D, C>::reverse_iterator
287         basic_ptree<K, D, C>::rend()
288     {
289         return reverse_iterator(this->begin());
290     }
291
292     template<class K, class D, class C> inline
293     typename basic_ptree<K, D, C>::const_reverse_iterator
294         basic_ptree<K, D, C>::rend() const
295     {
296         return const_reverse_iterator(this->begin());
297     }
298
299     template<class K, class D, class C> inline
300     typename basic_ptree<K, D, C>::value_type &
301         basic_ptree<K, D, C>::front()
302     {
303         return const_cast<value_type&>(subs::ch(this).front());
304     }
305
306     template<class K, class D, class C> inline
307     const typename basic_ptree<K, D, C>::value_type &
308         basic_ptree<K, D, C>::front() const
309     {
310         return subs::ch(this).front();
311     }
312
313     template<class K, class D, class C> inline
314     typename basic_ptree<K, D, C>::value_type &
315         basic_ptree<K, D, C>::back()
316     {
317         return const_cast<value_type&>(subs::ch(this).back());
318     }
319
320     template<class K, class D, class C> inline
321     const typename basic_ptree<K, D, C>::value_type &
322         basic_ptree<K, D, C>::back() const
323     {
324         return subs::ch(this).back();
325     }
326
327     template<class K, class D, class C> inline
328     typename basic_ptree<K, D, C>::iterator
329     basic_ptree<K, D, C>::insert(iterator where, const value_type &value)
330     {
331         return iterator(subs::ch(this).insert(where.base(), value).first);
332     }
333
334     template<class K, class D, class C>
335     template<class It> inline
336     void basic_ptree<K, D, C>::insert(iterator where, It first, It last)
337     {
338         subs::ch(this).insert(where.base(), first, last);
339     }
340
341     template<class K, class D, class C> inline
342     typename basic_ptree<K, D, C>::iterator
343         basic_ptree<K, D, C>::erase(iterator where)
344     {
345         return iterator(subs::ch(this).erase(where.base()));
346     }
347
348     template<class K, class D, class C> inline
349     typename basic_ptree<K, D, C>::iterator
350         basic_ptree<K, D, C>::erase(iterator first, iterator last)
351     {
352         return iterator(subs::ch(this).erase(first.base(), last.base()));
353     }
354
355     template<class K, class D, class C> inline
356     typename basic_ptree<K, D, C>::iterator
357         basic_ptree<K, D, C>::push_front(const value_type &value)
358     {
359         return iterator(subs::ch(this).push_front(value).first);
360     }
361
362     template<class K, class D, class C> inline
363     typename basic_ptree<K, D, C>::iterator
364         basic_ptree<K, D, C>::push_back(const value_type &value)
365     {
366         return iterator(subs::ch(this).push_back(value).first);
367     }
368
369     template<class K, class D, class C> inline
370     void basic_ptree<K, D, C>::pop_front()
371     {
372         subs::ch(this).pop_front();
373     }
374
375     template<class K, class D, class C> inline
376     void basic_ptree<K, D, C>::pop_back()
377     {
378         subs::ch(this).pop_back();
379     }
380
381     template<class K, class D, class C> inline
382     void basic_ptree<K, D, C>::reverse()
383     {
384         subs::ch(this).reverse();
385     }
386
387     template<class K, class D, class C> inline
388     void basic_ptree<K, D, C>::sort()
389     {
390         subs::ch(this).sort();
391     }
392
393     template<class K, class D, class C>
394     template<class Compare> inline
395     void basic_ptree<K, D, C>::sort(Compare comp)
396     {
397         subs::ch(this).sort(comp);
398     }
399
400     // Equality
401
402     template<class K, class D, class C> inline
403     bool basic_ptree<K, D, C>::operator ==(
404                                   const basic_ptree<K, D, C> &rhs) const
405     {
406         // The size test is cheap, so add it as an optimization
407         return size() == rhs.size() && data() == rhs.data() &&
408             subs::ch(this) == subs::ch(&rhs);
409     }
410
411     template<class K, class D, class C> inline
412     bool basic_ptree<K, D, C>::operator !=(
413                                   const basic_ptree<K, D, C> &rhs) const
414     {
415         return !(*this == rhs);
416     }
417
418     // Associative view
419
420     template<class K, class D, class C> inline
421     typename basic_ptree<K, D, C>::assoc_iterator
422         basic_ptree<K, D, C>::ordered_begin()
423     {
424         return assoc_iterator(subs::assoc(this).begin());
425     }
426
427     template<class K, class D, class C> inline
428     typename basic_ptree<K, D, C>::const_assoc_iterator
429         basic_ptree<K, D, C>::ordered_begin() const
430     {
431         return const_assoc_iterator(subs::assoc(this).begin());
432     }
433
434     template<class K, class D, class C> inline
435     typename basic_ptree<K, D, C>::assoc_iterator
436         basic_ptree<K, D, C>::not_found()
437     {
438         return assoc_iterator(subs::assoc(this).end());
439     }
440
441     template<class K, class D, class C> inline
442     typename basic_ptree<K, D, C>::const_assoc_iterator
443         basic_ptree<K, D, C>::not_found() const
444     {
445         return const_assoc_iterator(subs::assoc(this).end());
446     }
447
448     template<class K, class D, class C> inline
449     typename basic_ptree<K, D, C>::assoc_iterator
450         basic_ptree<K, D, C>::find(const key_type &key)
451     {
452         return assoc_iterator(subs::assoc(this).find(key));
453     }
454
455     template<class K, class D, class C> inline
456     typename basic_ptree<K, D, C>::const_assoc_iterator
457         basic_ptree<K, D, C>::find(const key_type &key) const
458     {
459         return const_assoc_iterator(subs::assoc(this).find(key));
460     }
461
462     template<class K, class D, class C> inline
463     std::pair<
464         typename basic_ptree<K, D, C>::assoc_iterator,
465         typename basic_ptree<K, D, C>::assoc_iterator
466     > basic_ptree<K, D, C>::equal_range(const key_type &key)
467     {
468         std::pair<typename subs::by_name_index::iterator,
469                   typename subs::by_name_index::iterator> r(
470             subs::assoc(this).equal_range(key));
471         return std::pair<assoc_iterator, assoc_iterator>(
472           assoc_iterator(r.first), assoc_iterator(r.second));
473     }
474
475     template<class K, class D, class C> inline
476     std::pair<
477         typename basic_ptree<K, D, C>::const_assoc_iterator,
478         typename basic_ptree<K, D, C>::const_assoc_iterator
479     > basic_ptree<K, D, C>::equal_range(const key_type &key) const
480     {
481         std::pair<typename subs::by_name_index::const_iterator,
482                   typename subs::by_name_index::const_iterator> r(
483             subs::assoc(this).equal_range(key));
484         return std::pair<const_assoc_iterator, const_assoc_iterator>(
485             const_assoc_iterator(r.first), const_assoc_iterator(r.second));
486     }
487
488     template<class K, class D, class C> inline
489     typename basic_ptree<K, D, C>::size_type
490         basic_ptree<K, D, C>::count(const key_type &key) const
491     {
492         return subs::assoc(this).count(key);
493     }
494
495     template<class K, class D, class C> inline
496     typename basic_ptree<K, D, C>::size_type
497         basic_ptree<K, D, C>::erase(const key_type &key)
498     {
499         return subs::assoc(this).erase(key);
500     }
501
502     template<class K, class D, class C> inline
503     typename basic_ptree<K, D, C>::iterator
504         basic_ptree<K, D, C>::to_iterator(assoc_iterator ai)
505     {
506         return iterator(subs::ch(this).
507             BOOST_NESTED_TEMPLATE project<0>(ai.base()));
508     }
509
510     template<class K, class D, class C> inline
511     typename basic_ptree<K, D, C>::const_iterator
512         basic_ptree<K, D, C>::to_iterator(const_assoc_iterator ai) const
513     {
514         return const_iterator(subs::ch(this).
515             BOOST_NESTED_TEMPLATE project<0>(ai.base()));
516     }
517
518     // Property tree view
519
520     template<class K, class D, class C> inline
521     typename basic_ptree<K, D, C>::data_type &
522         basic_ptree<K, D, C>::data()
523     {
524         return m_data;
525     }
526
527     template<class K, class D, class C> inline
528     const typename basic_ptree<K, D, C>::data_type &
529         basic_ptree<K, D, C>::data() const
530     {
531         return m_data;
532     }
533
534     template<class K, class D, class C> inline
535     void basic_ptree<K, D, C>::clear()
536     {
537         m_data = data_type();
538         subs::ch(this).clear();
539     }
540
541     template<class K, class D, class C>
542     basic_ptree<K, D, C> &
543         basic_ptree<K, D, C>::get_child(const path_type &path)
544     {
545         path_type p(path);
546         self_type *n = walk_path(p);
547         if (!n) {
548             BOOST_PROPERTY_TREE_THROW(ptree_bad_path("No such node", path));
549         }
550         return *n;
551     }
552
553     template<class K, class D, class C> inline
554     const basic_ptree<K, D, C> &
555         basic_ptree<K, D, C>::get_child(const path_type &path) const
556     {
557         return const_cast<self_type*>(this)->get_child(path);
558     }
559
560     template<class K, class D, class C> inline
561     basic_ptree<K, D, C> &
562         basic_ptree<K, D, C>::get_child(const path_type &path,
563                                         self_type &default_value)
564     {
565         path_type p(path);
566         self_type *n = walk_path(p);
567         return n ? *n : default_value;
568     }
569
570     template<class K, class D, class C> inline
571     const basic_ptree<K, D, C> &
572         basic_ptree<K, D, C>::get_child(const path_type &path,
573                                         const self_type &default_value) const
574     {
575         return const_cast<self_type*>(this)->get_child(path,
576             const_cast<self_type&>(default_value));
577     }
578
579
580     template<class K, class D, class C>
581     optional<basic_ptree<K, D, C> &>
582         basic_ptree<K, D, C>::get_child_optional(const path_type &path)
583     {
584         path_type p(path);
585         self_type *n = walk_path(p);
586         if (!n) {
587             return optional<self_type&>();
588         }
589         return *n;
590     }
591
592     template<class K, class D, class C>
593     optional<const basic_ptree<K, D, C> &>
594         basic_ptree<K, D, C>::get_child_optional(const path_type &path) const
595     {
596         path_type p(path);
597         self_type *n = walk_path(p);
598         if (!n) {
599             return optional<const self_type&>();
600         }
601         return *n;
602     }
603
604     template<class K, class D, class C>
605     basic_ptree<K, D, C> &
606         basic_ptree<K, D, C>::put_child(const path_type &path,
607                                         const self_type &value)
608     {
609         path_type p(path);
610         self_type &parent = force_path(p);
611         // Got the parent. Now get the correct child.
612         key_type fragment = p.reduce();
613         assoc_iterator el = parent.find(fragment);
614         // If the new child exists, replace it.
615         if(el != parent.not_found()) {
616             return el->second = value;
617         } else {
618             return parent.push_back(value_type(fragment, value))->second;
619         }
620     }
621
622     template<class K, class D, class C>
623     basic_ptree<K, D, C> &
624         basic_ptree<K, D, C>::add_child(const path_type &path,
625                                         const self_type &value)
626     {
627         path_type p(path);
628         self_type &parent = force_path(p);
629         // Got the parent.
630         key_type fragment = p.reduce();
631         return parent.push_back(value_type(fragment, value))->second;
632     }
633
634     template<class K, class D, class C>
635     template<class Type, class Translator>
636     typename boost::enable_if<detail::is_translator<Translator>, Type>::type
637     basic_ptree<K, D, C>::get_value(Translator tr) const
638     {
639         if(boost::optional<Type> o = get_value_optional<Type>(tr)) {
640             return *o;
641         }
642         BOOST_PROPERTY_TREE_THROW(ptree_bad_data(
643             std::string("conversion of data to type \"") +
644             typeid(Type).name() + "\" failed", data()));
645     }
646
647     template<class K, class D, class C>
648     template<class Type> inline
649     Type basic_ptree<K, D, C>::get_value() const
650     {
651         return get_value<Type>(
652             typename translator_between<data_type, Type>::type());
653     }
654
655     template<class K, class D, class C>
656     template<class Type, class Translator> inline
657     Type basic_ptree<K, D, C>::get_value(const Type &default_value,
658                                          Translator tr) const
659     {
660         return get_value_optional<Type>(tr).get_value_or(default_value);
661     }
662
663     template<class K, class D, class C>
664     template <class Ch, class Translator>
665     typename boost::enable_if<
666         detail::is_character<Ch>,
667         std::basic_string<Ch>
668     >::type
669     basic_ptree<K, D, C>::get_value(const Ch *default_value, Translator tr)const
670     {
671         return get_value<std::basic_string<Ch>, Translator>(default_value, tr);
672     }
673
674     template<class K, class D, class C>
675     template<class Type> inline
676     typename boost::disable_if<detail::is_translator<Type>, Type>::type
677     basic_ptree<K, D, C>::get_value(const Type &default_value) const
678     {
679         return get_value(default_value,
680                          typename translator_between<data_type, Type>::type());
681     }
682
683     template<class K, class D, class C>
684     template <class Ch>
685     typename boost::enable_if<
686         detail::is_character<Ch>,
687         std::basic_string<Ch>
688     >::type
689     basic_ptree<K, D, C>::get_value(const Ch *default_value) const
690     {
691         return get_value< std::basic_string<Ch> >(default_value);
692     }
693
694     template<class K, class D, class C>
695     template<class Type, class Translator> inline
696     optional<Type> basic_ptree<K, D, C>::get_value_optional(
697                                                 Translator tr) const
698     {
699         return tr.get_value(data());
700     }
701
702     template<class K, class D, class C>
703     template<class Type> inline
704     optional<Type> basic_ptree<K, D, C>::get_value_optional() const
705     {
706         return get_value_optional<Type>(
707             typename translator_between<data_type, Type>::type());
708     }
709
710     template<class K, class D, class C>
711     template<class Type, class Translator> inline
712     typename boost::enable_if<detail::is_translator<Translator>, Type>::type
713     basic_ptree<K, D, C>::get(const path_type &path,
714                               Translator tr) const
715     {
716         return get_child(path).BOOST_NESTED_TEMPLATE get_value<Type>(tr);
717     }
718
719     template<class K, class D, class C>
720     template<class Type> inline
721     Type basic_ptree<K, D, C>::get(const path_type &path) const
722     {
723         return get_child(path).BOOST_NESTED_TEMPLATE get_value<Type>();
724     }
725
726     template<class K, class D, class C>
727     template<class Type, class Translator> inline
728     Type basic_ptree<K, D, C>::get(const path_type &path,
729                                    const Type &default_value,
730                                    Translator tr) const
731     {
732         return get_optional<Type>(path, tr).get_value_or(default_value);
733     }
734
735     template<class K, class D, class C>
736     template <class Ch, class Translator>
737     typename boost::enable_if<
738         detail::is_character<Ch>,
739         std::basic_string<Ch>
740     >::type
741     basic_ptree<K, D, C>::get(
742         const path_type &path, const Ch *default_value, Translator tr) const
743     {
744         return get<std::basic_string<Ch>, Translator>(path, default_value, tr);
745     }
746
747     template<class K, class D, class C>
748     template<class Type> inline
749     typename boost::disable_if<detail::is_translator<Type>, Type>::type
750     basic_ptree<K, D, C>::get(const path_type &path,
751                               const Type &default_value) const
752     {
753         return get_optional<Type>(path).get_value_or(default_value);
754     }
755
756     template<class K, class D, class C>
757     template <class Ch>
758     typename boost::enable_if<
759         detail::is_character<Ch>,
760         std::basic_string<Ch>
761     >::type
762     basic_ptree<K, D, C>::get(
763         const path_type &path, const Ch *default_value) const
764     {
765         return get< std::basic_string<Ch> >(path, default_value);
766     }
767
768     template<class K, class D, class C>
769     template<class Type, class Translator>
770     optional<Type> basic_ptree<K, D, C>::get_optional(const path_type &path,
771                                                          Translator tr) const
772     {
773         if (optional<const self_type&> child = get_child_optional(path))
774             return child.get().
775                 BOOST_NESTED_TEMPLATE get_value_optional<Type>(tr);
776         else
777             return optional<Type>();
778     }
779
780     template<class K, class D, class C>
781     template<class Type>
782     optional<Type> basic_ptree<K, D, C>::get_optional(
783                                                 const path_type &path) const
784     {
785         if (optional<const self_type&> child = get_child_optional(path))
786             return child.get().BOOST_NESTED_TEMPLATE get_value_optional<Type>();
787         else
788             return optional<Type>();
789     }
790
791     template<class K, class D, class C>
792     template<class Type, class Translator>
793     void basic_ptree<K, D, C>::put_value(const Type &value, Translator tr)
794     {
795         if(optional<data_type> o = tr.put_value(value)) {
796             data() = *o;
797         } else {
798             BOOST_PROPERTY_TREE_THROW(ptree_bad_data(
799                 std::string("conversion of type \"") + typeid(Type).name() +
800                 "\" to data failed", boost::any()));
801         }
802     }
803
804     template<class K, class D, class C>
805     template<class Type> inline
806     void basic_ptree<K, D, C>::put_value(const Type &value)
807     {
808         put_value(value, typename translator_between<data_type, Type>::type());
809     }
810
811     template<class K, class D, class C>
812     template<class Type, typename Translator>
813     basic_ptree<K, D, C> & basic_ptree<K, D, C>::put(
814         const path_type &path, const Type &value, Translator tr)
815     {
816         if(optional<self_type &> child = get_child_optional(path)) {
817             child.get().put_value(value, tr);
818             return *child;
819         } else {
820             self_type &child2 = put_child(path, self_type());
821             child2.put_value(value, tr);
822             return child2;
823         }
824     }
825
826     template<class K, class D, class C>
827     template<class Type> inline
828     basic_ptree<K, D, C> & basic_ptree<K, D, C>::put(
829         const path_type &path, const Type &value)
830     {
831         return put(path, value,
832                    typename translator_between<data_type, Type>::type());
833     }
834
835     template<class K, class D, class C>
836     template<class Type, typename Translator> inline
837     basic_ptree<K, D, C> & basic_ptree<K, D, C>::add(
838         const path_type &path, const Type &value, Translator tr)
839     {
840         self_type &child = add_child(path, self_type());
841         child.put_value(value, tr);
842         return child;
843     }
844
845     template<class K, class D, class C>
846     template<class Type> inline
847     basic_ptree<K, D, C> & basic_ptree<K, D, C>::add(
848         const path_type &path, const Type &value)
849     {
850         return add(path, value,
851                    typename translator_between<data_type, Type>::type());
852     }
853
854
855     template<class K, class D, class C>
856     basic_ptree<K, D, C> *
857     basic_ptree<K, D, C>::walk_path(path_type &p) const
858     {
859         if(p.empty()) {
860             // I'm the child we're looking for.
861             return const_cast<basic_ptree*>(this);
862         }
863         // Recurse down the tree to find the path.
864         key_type fragment = p.reduce();
865         const_assoc_iterator el = find(fragment);
866         if(el == not_found()) {
867             // No such child.
868             return 0;
869         }
870         // Not done yet, recurse.
871         return el->second.walk_path(p);
872     }
873
874     template<class K, class D, class C>
875     basic_ptree<K, D, C> & basic_ptree<K, D, C>::force_path(path_type &p)
876     {
877         BOOST_ASSERT(!p.empty() && "Empty path not allowed for put_child.");
878         if(p.single()) {
879             // I'm the parent we're looking for.
880             return *this;
881         }
882         key_type fragment = p.reduce();
883         assoc_iterator el = find(fragment);
884         // If we've found an existing child, go down that path. Else
885         // create a new one.
886         self_type& child = el == not_found() ?
887             push_back(value_type(fragment, self_type()))->second : el->second;
888         return child.force_path(p);
889     }
890
891     // Free functions
892
893     template<class K, class D, class C>
894     inline void swap(basic_ptree<K, D, C> &pt1, basic_ptree<K, D, C> &pt2)
895     {
896         pt1.swap(pt2);
897     }
898
899 } }
900
901 #if defined(BOOST_PROPERTY_TREE_PAIR_BUG)
902 #undef BOOST_PROPERTY_TREE_PAIR_BUG
903 #endif
904
905 #endif