]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/FGPropertyManager.h
Updates. Includes property tree additions and fixes. Also Jon's first cut at
[flightgear.git] / src / FDM / JSBSim / FGPropertyManager.h
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2  
3  Header:       FGPropertyManager.h
4  Author:       Tony Peden
5                Based on work originally by David Megginson
6  Date:         2/2002
7  
8  ------------- Copyright (C) 2002 -------------
9  
10  This program is free software; you can redistribute it and/or modify it under
11  the terms of the GNU General Public License as published by the Free Software
12  Foundation; either version 2 of the License, or (at your option) any later
13  version.
14  
15  This program is distributed in the hope that it will be useful, but WITHOUT
16  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
18  details.
19  
20  You should have received a copy of the GNU General Public License along with
21  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
22  Place - Suite 330, Boston, MA  02111-1307, USA.
23
24  Further information about the GNU General Public License can also be found on
25  the world wide web at http://www.gnu.org.
26  
27 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
28 SENTRY
29 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
30
31 #ifndef FGPROPERTYMANAGER_H
32 #define FGPROPERTYMANAGER_H
33
34 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 INCLUDES
36 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
37
38 #include <simgear/misc/props.hxx>
39
40 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
41 DEFINITIONS
42 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
43
44 #define ID_PROPERTYMANAGER "$Id$"
45
46 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
47 FORWARD DECLARATIONS
48 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
49
50 using namespace std;
51
52 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
53 COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs]
54 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
55
56 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
57 CLASS DOCUMENTATION
58 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
59
60 /** Class wrapper for property handling.
61     @author David Megginson, Tony Peden
62     @see <a href="http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/jsbsim/JSBSim/FGPropertyManager.h?rev=HEAD&content-type=text/vnd.viewcvs-markup">
63          Header File </a>
64   */
65   
66 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
67 CLASS DECLARATION
68 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
69
70 class FGPropertyManager:public SGPropertyNode {
71   public:
72     /// Constructor
73     FGPropertyManager(void) {
74       
75     }
76     /// Destructor
77     ~FGPropertyManager(void) {
78       
79     }   
80     /**
81      * Get a property node.
82      *
83      * @param path The path of the node, relative to root.
84      * @param create true to create the node if it doesn't exist.
85      * @return The node, or 0 if none exists and none was created.
86      */
87     inline FGPropertyManager* 
88     GetNode (const string &path, bool create = false)
89     {
90       SGPropertyNode* node=this->getNode(path.c_str(), create);
91       if(node == 0) 
92         cout << "FGPropertyManager::GetNode() No node found for " 
93              << path << endl;
94       return (FGPropertyManager*)node;
95     }
96   
97     inline FGPropertyManager* 
98     GetNode (const string &relpath, int index, bool create = false)
99     {
100         return (FGPropertyManager*)getNode(relpath.c_str(),index,create);
101     }    
102
103
104     /**
105      * Test whether a given node exists.
106      *
107      * @param path The path of the node, relative to root.
108      * @return true if the node exists, false otherwise.
109      */
110     inline bool
111     HasNode (const string &path)
112     {
113       return (GetNode(path, false) != 0);
114     }
115
116
117     /**
118      * Get a bool value for a property.
119      *
120      * This method is convenient but inefficient.  It should be used
121      * infrequently (i.e. for initializing, loading, saving, etc.),
122      * not in the main loop.  If you need to get a value frequently,
123      * it is better to look up the node itself using GetNode and then
124      * use the node's getBoolValue() method, to avoid the lookup overhead.
125      *
126      * @param name The property name.
127      * @param defaultValue The default value to return if the property
128      *        does not exist.
129      * @return The property's value as a bool, or the default value provided.
130      */
131     inline bool GetBool (const string &name, bool defaultValue = false)
132     {
133       return getBoolValue(name.c_str(), defaultValue);
134     }
135
136
137     /**
138      * Get an int value for a property.
139      *
140      * This method is convenient but inefficient.  It should be used
141      * infrequently (i.e. for initializing, loading, saving, etc.),
142      * not in the main loop.  If you need to get a value frequently,
143      * it is better to look up the node itself using GetNode and then
144      * use the node's getIntValue() method, to avoid the lookup overhead.
145      *
146      * @param name The property name.
147      * @param defaultValue The default value to return if the property
148      *        does not exist.
149      * @return The property's value as an int, or the default value provided.
150      */
151     inline int GetInt (const string &name, int defaultValue = 0)
152     {
153       return getIntValue(name.c_str(), defaultValue);
154     }
155
156
157     /**
158      * Get a long value for a property.
159      *
160      * This method is convenient but inefficient.  It should be used
161      * infrequently (i.e. for initializing, loading, saving, etc.),
162      * not in the main loop.  If you need to get a value frequently,
163      * it is better to look up the node itself using GetNode and then
164      * use the node's getLongValue() method, to avoid the lookup overhead.
165      *
166      * @param name The property name.
167      * @param defaultValue The default value to return if the property
168      *        does not exist.
169      * @return The property's value as a long, or the default value provided.
170      */
171     inline int GetLong (const string &name, long defaultValue = 0L)
172     {
173       return getLongValue(name.c_str(), defaultValue);
174     }
175
176
177     /**
178      * Get a float value for a property.
179      *
180      * This method is convenient but inefficient.  It should be used
181      * infrequently (i.e. for initializing, loading, saving, etc.),
182      * not in the main loop.  If you need to get a value frequently,
183      * it is better to look up the node itself using GetNode and then
184      * use the node's getFloatValue() method, to avoid the lookup overhead.
185      *
186      * @param name The property name.
187      * @param defaultValue The default value to return if the property
188      *        does not exist.
189      * @return The property's value as a float, or the default value provided.
190      */
191     inline float GetFloat (const string &name, float defaultValue = 0.0)
192     {
193       return getFloatValue(name.c_str(), defaultValue);
194     }
195
196
197     /**
198      * Get a double value for a property.
199      *
200      * This method is convenient but inefficient.  It should be used
201      * infrequently (i.e. for initializing, loading, saving, etc.),
202      * not in the main loop.  If you need to get a value frequently,
203      * it is better to look up the node itself using GetNode and then
204      * use the node's getDoubleValue() method, to avoid the lookup overhead.
205      *
206      * @param name The property name.
207      * @param defaultValue The default value to return if the property
208      *        does not exist.
209      * @return The property's value as a double, or the default value provided.
210      */
211     inline double GetDouble (const string &name, double defaultValue = 0.0)
212     {
213       return getDoubleValue(name.c_str(), defaultValue);
214     }
215
216
217     /**
218      * Get a string value for a property.
219      *
220      * This method is convenient but inefficient.  It should be used
221      * infrequently (i.e. for initializing, loading, saving, etc.),
222      * not in the main loop.  If you need to get a value frequently,
223      * it is better to look up the node itself using GetNode and then
224      * use the node's getStringValue() method, to avoid the lookup overhead.
225      *
226      * @param name The property name.
227      * @param defaultValue The default value to return if the property
228      *        does not exist.
229      * @return The property's value as a string, or the default value provided.
230      */
231     inline string GetString (const string &name, string defaultValue = "")
232     {
233       return string(getStringValue(name.c_str(), defaultValue.c_str()));
234     }
235
236
237     /**
238      * Set a bool value for a property.
239      *
240      * Assign a bool value to a property.  If the property does not
241      * yet exist, it will be created and its type will be set to
242      * BOOL; if it has a type of UNKNOWN, the type will also be set to
243      * BOOL; otherwise, the bool value will be converted to the property's
244      * type.
245      *
246      * @param name The property name.
247      * @param val The new value for the property.
248      * @return true if the assignment succeeded, false otherwise.
249      */
250     inline bool SetBool (const string &name, bool val)
251     {
252       return setBoolValue(name.c_str(), val);
253     }
254
255
256     /**
257      * Set an int value for a property.
258      *
259      * Assign an int value to a property.  If the property does not
260      * yet exist, it will be created and its type will be set to
261      * INT; if it has a type of UNKNOWN, the type will also be set to
262      * INT; otherwise, the bool value will be converted to the property's
263      * type.
264      *
265      * @param name The property name.
266      * @param val The new value for the property.
267      * @return true if the assignment succeeded, false otherwise.
268      */
269     inline bool SetInt (const string &name, int val)
270     {
271       return setIntValue(name.c_str(), val);
272     }
273
274
275     /**
276      * Set a long value for a property.
277      *
278      * Assign a long value to a property.  If the property does not
279      * yet exist, it will be created and its type will be set to
280      * LONG; if it has a type of UNKNOWN, the type will also be set to
281      * LONG; otherwise, the bool value will be converted to the property's
282      * type.
283      *
284      * @param name The property name.
285      * @param val The new value for the property.
286      * @return true if the assignment succeeded, false otherwise.
287      */
288     inline bool SetLong (const string &name, long val)
289     {
290       return setLongValue(name.c_str(), val);
291     }
292
293
294     /**
295      * Set a float value for a property.
296      *
297      * Assign a float value to a property.  If the property does not
298      * yet exist, it will be created and its type will be set to
299      * FLOAT; if it has a type of UNKNOWN, the type will also be set to
300      * FLOAT; otherwise, the bool value will be converted to the property's
301      * type.
302      *
303      * @param name The property name.
304      * @param val The new value for the property.
305      * @return true if the assignment succeeded, false otherwise.
306      */
307     inline bool SetFloat (const string &name, float val)
308     {
309       return setFloatValue(name.c_str(), val);
310     }
311
312
313     /**
314      * Set a double value for a property.
315      *
316      * Assign a double value to a property.  If the property does not
317      * yet exist, it will be created and its type will be set to
318      * DOUBLE; if it has a type of UNKNOWN, the type will also be set to
319      * DOUBLE; otherwise, the double value will be converted to the property's
320      * type.
321      *
322      * @param name The property name.
323      * @param val The new value for the property.
324      * @return true if the assignment succeeded, false otherwise.
325      */
326     inline bool SetDouble (const string &name, double val)
327     {
328       return setDoubleValue(name.c_str(), val);
329     }
330
331
332     /**
333      * Set a string value for a property.
334      *
335      * Assign a string value to a property.  If the property does not
336      * yet exist, it will be created and its type will be set to
337      * STRING; if it has a type of UNKNOWN, the type will also be set to
338      * STRING; otherwise, the string value will be converted to the property's
339      * type.
340      *
341      * @param name The property name.
342      * @param val The new value for the property.
343      * @return true if the assignment succeeded, false otherwise.
344      */
345     inline bool SetString (const string &name, const string &val)
346     {
347       return setStringValue(name.c_str(), val.c_str());
348     }
349
350
351     \f
352     ////////////////////////////////////////////////////////////////////////
353     // Convenience functions for setting property attributes.
354     ////////////////////////////////////////////////////////////////////////
355
356
357     /**
358      * Set the state of the archive attribute for a property.
359      *
360      * If the archive attribute is true, the property will be written
361      * when a flight is saved; if it is false, the property will be
362      * skipped.
363      *
364      * A warning message will be printed if the property does not exist.
365      *
366      * @param name The property name.
367      * @param state The state of the archive attribute (defaults to true).
368      */
369     inline void
370     SetArchivable (const string &name, bool state = true)
371     {
372       SGPropertyNode * node = getNode(name.c_str());
373       if (node == 0)
374         cout <<
375                "Attempt to set archive flag for non-existant property "
376                << name;
377       else
378         node->setAttribute(SGPropertyNode::ARCHIVE, state);
379     }
380
381
382     /**
383      * Set the state of the read attribute for a property.
384      *
385      * If the read attribute is true, the property value will be readable;
386      * if it is false, the property value will always be the default value
387      * for its type.
388      *
389      * A warning message will be printed if the property does not exist.
390      *
391      * @param name The property name.
392      * @param state The state of the read attribute (defaults to true).
393      */
394     inline void
395     SetReadable (const string &name, bool state = true)
396     {
397       SGPropertyNode * node = getNode(name.c_str());
398       if (node == 0)
399         cout <<
400                "Attempt to set read flag for non-existant property "
401                << name;
402       else
403         node->setAttribute(SGPropertyNode::READ, state);
404     }
405
406
407     /**
408      * Set the state of the write attribute for a property.
409      *
410      * If the write attribute is true, the property value may be modified
411      * (depending on how it is tied); if the write attribute is false, the
412      * property value may not be modified.
413      *
414      * A warning message will be printed if the property does not exist.
415      *
416      * @param name The property name.
417      * @param state The state of the write attribute (defaults to true).
418      */
419     inline void
420     SetWritable (const string &name, bool state = true)
421     {
422       SGPropertyNode * node = getNode(name.c_str());
423       if (node == 0)
424         cout <<
425                "Attempt to set write flag for non-existant property "
426                << name;
427       else
428         node->setAttribute(SGPropertyNode::WRITE, state);
429     }
430
431
432     \f
433     ////////////////////////////////////////////////////////////////////////
434     // Convenience functions for tying properties, with logging.
435     ////////////////////////////////////////////////////////////////////////
436
437
438     /**
439      * Untie a property from an external data source.
440      *
441      * Classes should use this function to release control of any
442      * properties they are managing.
443      */
444     inline void
445     Untie (const string &name)
446     {
447       if (!untie(name.c_str()))
448         cout << "Failed to untie property " << name;
449     }
450
451
452                                     // Templates cause ambiguity here
453
454     /**
455      * Tie a property to an external bool variable.
456      *
457      * The property's value will automatically mirror the variable's
458      * value, and vice-versa, until the property is untied.
459      *
460      * @param name The property name to tie (full path).
461      * @param pointer A pointer to the variable.
462      * @param useDefault true if any existing property value should be
463      *        copied to the variable; false if the variable should not
464      *        be modified; defaults to true.
465      */
466     inline void
467     Tie (const string &name, bool *pointer, bool useDefault = true)
468     {
469       if (!tie(name.c_str(), SGRawValuePointer<bool>(pointer),
470                                      useDefault))
471         cout <<
472                "Failed to tie property " << name << " to a pointer";
473     }
474
475
476     /**
477      * Tie a property to an external int variable.
478      *
479      * The property's value will automatically mirror the variable's
480      * value, and vice-versa, until the property is untied.
481      *
482      * @param name The property name to tie (full path).
483      * @param pointer A pointer to the variable.
484      * @param useDefault true if any existing property value should be
485      *        copied to the variable; false if the variable should not
486      *        be modified; defaults to true.
487      */
488     inline void
489     Tie (const string &name, int *pointer, bool useDefault = true)
490     {
491       if (!tie(name.c_str(), SGRawValuePointer<int>(pointer),
492                                      useDefault))
493         cout <<
494                "Failed to tie property " << name << " to a pointer";
495     }
496
497
498     /**
499      * Tie a property to an external long variable.
500      *
501      * The property's value will automatically mirror the variable's
502      * value, and vice-versa, until the property is untied.
503      *
504      * @param name The property name to tie (full path).
505      * @param pointer A pointer to the variable.
506      * @param useDefault true if any existing property value should be
507      *        copied to the variable; false if the variable should not
508      *        be modified; defaults to true.
509      */
510     inline void
511     Tie (const string &name, long *pointer, bool useDefault = true)
512     {
513       if (!tie(name.c_str(), SGRawValuePointer<long>(pointer),
514                                      useDefault))
515         cout <<
516                "Failed to tie property " << name << " to a pointer";
517     }
518
519
520     /**
521      * Tie a property to an external float variable.
522      *
523      * The property's value will automatically mirror the variable's
524      * value, and vice-versa, until the property is untied.
525      *
526      * @param name The property name to tie (full path).
527      * @param pointer A pointer to the variable.
528      * @param useDefault true if any existing property value should be
529      *        copied to the variable; false if the variable should not
530      *        be modified; defaults to true.
531      */
532     inline void
533     Tie (const string &name, float *pointer, bool useDefault = true)
534     {
535       if (!tie(name.c_str(), SGRawValuePointer<float>(pointer),
536                                      useDefault))
537         cout <<
538                "Failed to tie property " << name << " to a pointer";
539     }
540
541
542     /**
543      * Tie a property to an external double variable.
544      *
545      * The property's value will automatically mirror the variable's
546      * value, and vice-versa, until the property is untied.
547      *
548      * @param name The property name to tie (full path).
549      * @param pointer A pointer to the variable.
550      * @param useDefault true if any existing property value should be
551      *        copied to the variable; false if the variable should not
552      *        be modified; defaults to true.
553      */
554     inline void
555     Tie (const string &name, double *pointer, bool useDefault = true)
556     {
557       if (!tie(name.c_str(), SGRawValuePointer<double>(pointer),
558                                      useDefault))
559         cout <<
560                "Failed to tie property " << name << " to a pointer";
561     }
562
563     /* template <class V> void
564     Tie (const string &name, V (*getter)(), void (*setter)(V) = 0,
565            bool useDefault = true);
566     
567     template <class V> void
568     Tie (const string &name, int index, V (*getter)(int),
569            void (*setter)(int, V) = 0, bool useDefault = true);
570     
571     template <class T, class V> void
572     Tie (const string &name, T * obj, V (T::*getter)() const,
573            void (T::*setter)(V) = 0, bool useDefault = true);
574
575     template <class T, class V> void 
576     Tie (const string &name, T * obj, int index,
577            V (T::*getter)(int) const, void (T::*setter)(int, V) = 0,
578            bool useDefault = true); */
579
580 /**
581      * Tie a property to a pair of simple functions.
582      *
583      * Every time the property value is queried, the getter (if any) will
584      * be invoked; every time the property value is modified, the setter
585      * (if any) will be invoked.  The getter can be 0 to make the property
586      * unreadable, and the setter can be 0 to make the property
587      * unmodifiable.
588      *
589      * @param name The property name to tie (full path).
590      * @param getter The getter function, or 0 if the value is unreadable.
591      * @param setter The setter function, or 0 if the value is unmodifiable.
592      * @param useDefault true if the setter should be invoked with any existing 
593      *        property value should be; false if the old value should be
594      *        discarded; defaults to true.
595      */
596     template <class V>
597     inline void
598     Tie (const string &name, V (*getter)(), void (*setter)(V) = 0,
599            bool useDefault = true)
600     {
601       if (!tie(name.c_str(), SGRawValueFunctions<V>(getter, setter),
602                                      useDefault))
603         cout <<
604                "Failed to tie property " << name << " to functions";
605     }
606
607
608     /**
609      * Tie a property to a pair of indexed functions.
610      *
611      * Every time the property value is queried, the getter (if any) will
612      * be invoked with the index provided; every time the property value
613      * is modified, the setter (if any) will be invoked with the index
614      * provided.  The getter can be 0 to make the property unreadable, and
615      * the setter can be 0 to make the property unmodifiable.
616      *
617      * @param name The property name to tie (full path).
618      * @param index The integer argument to pass to the getter and
619      *        setter functions.
620      * @param getter The getter function, or 0 if the value is unreadable.
621      * @param setter The setter function, or 0 if the value is unmodifiable.
622      * @param useDefault true if the setter should be invoked with any existing 
623      *        property value should be; false if the old value should be
624      *        discarded; defaults to true.
625      */
626     template <class V>
627     inline void
628     Tie (const string &name, int index, V (*getter)(int),
629            void (*setter)(int, V) = 0, bool useDefault = true)
630     {
631       if (!tie(name.c_str(),
632                                      SGRawValueFunctionsIndexed<V>(index,
633                                                                    getter,
634                                                                    setter),
635                                      useDefault))
636         cout <<
637                "Failed to tie property " << name << " to indexed functions";
638     }
639
640
641     /**
642      * Tie a property to a pair of object methods.
643      *
644      * Every time the property value is queried, the getter (if any) will
645      * be invoked; every time the property value is modified, the setter
646      * (if any) will be invoked.  The getter can be 0 to make the property
647      * unreadable, and the setter can be 0 to make the property
648      * unmodifiable.
649      *
650      * @param name The property name to tie (full path).
651      * @param obj The object whose methods should be invoked.
652      * @param getter The object's getter method, or 0 if the value is
653      *        unreadable.
654      * @param setter The object's setter method, or 0 if the value is
655      *        unmodifiable.
656      * @param useDefault true if the setter should be invoked with any existing 
657      *        property value should be; false if the old value should be
658      *        discarded; defaults to true.
659      */
660     template <class T, class V>
661     inline void
662     Tie (const string &name, T * obj, V (T::*getter)() const,
663            void (T::*setter)(V) = 0, bool useDefault = true)
664     {
665       if (!tie(name.c_str(),
666                                      SGRawValueMethods<T,V>(*obj, getter, setter),
667                                      useDefault))
668         cout <<
669                "Failed to tie property " << name << " to object methods";
670     }
671
672
673     /**
674      * Tie a property to a pair of indexed object methods.
675      *
676      * Every time the property value is queried, the getter (if any) will
677      * be invoked with the index provided; every time the property value
678      * is modified, the setter (if any) will be invoked with the index
679      * provided.  The getter can be 0 to make the property unreadable, and
680      * the setter can be 0 to make the property unmodifiable.
681      *
682      * @param name The property name to tie (full path).
683      * @param obj The object whose methods should be invoked.
684      * @param index The integer argument to pass to the getter and
685      *        setter methods.
686      * @param getter The getter method, or 0 if the value is unreadable.
687      * @param setter The setter method, or 0 if the value is unmodifiable.
688      * @param useDefault true if the setter should be invoked with any existing 
689      *        property value should be; false if the old value should be
690      *        discarded; defaults to true.
691      */
692     template <class T, class V>
693     inline void 
694     Tie (const string &name, T * obj, int index,
695            V (T::*getter)(int) const, void (T::*setter)(int, V) = 0,
696            bool useDefault = true)
697     {
698       if (!tie(name.c_str(),
699                                      SGRawValueMethodsIndexed<T,V>(*obj,
700                                                                    index,
701                                                                    getter,
702                                                                    setter),
703                                      useDefault))
704         cout <<
705                "Failed to tie property " << name << " to indexed object methods";
706     }
707
708 };        
709
710
711 #endif // FGPROPERTYMANAGER_H
712