Skip to content

Commit

Permalink
Use templates for FGPropertyManager::Tie of a pointer.
Browse files Browse the repository at this point in the history
According to the comments this method was instanciated manually for all types of pointers because otherwise it was confusing compilers. Well, it seems modern compilers can resolve the ambiguity so we can now use templates to avoid code duplication.

Took this opportunity to use nullptr instead of 0 in other templates.
  • Loading branch information
bcoconni committed Apr 30, 2021
1 parent 79be337 commit 9a01cea
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 222 deletions.
104 changes: 4 additions & 100 deletions src/input_output/FGPropertyManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,10 @@ namespace JSBSim {

void FGPropertyManager::Unbind(void)
{
vector<SGPropertyNode_ptr>::iterator it;
for(auto& prop: tied_properties)
prop->untie();

for (it = tied_properties.begin();it < tied_properties.end();it++)
(*it)->untie();

tied_properties.clear();
tied_properties.clear();
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Expand All @@ -73,7 +71,7 @@ string FGPropertyManager::mkPropertyName(string name, bool lowercase) {
else if( isspace(name[i]) )
name[i]='-';
}

return name;
}

Expand Down Expand Up @@ -324,98 +322,4 @@ void FGPropertyManager::Untie (const string &name)
cerr << "Failed to untie property " << name << endl
<< "JSBSim is not the owner of this property." << endl;
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void FGPropertyManager::Tie (const string &name, bool *pointer, bool useDefault)
{
SGPropertyNode* property = root->getNode(name.c_str(), true);
if (!property) {
cerr << "Could not get or create property " << name << endl;
return;
}

if (!property->tie(SGRawValuePointer<bool>(pointer), useDefault))
cerr << "Failed to tie property " << name << " to a pointer" << endl;
else {
tied_properties.push_back(property);
if (FGJSBBase::debug_lvl & 0x20) cout << name << endl;
}
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void FGPropertyManager::Tie (const string &name, int *pointer,
bool useDefault )
{
SGPropertyNode* property = root->getNode(name.c_str(), true);
if (!property) {
cerr << "Could not get or create property " << name << endl;
return;
}

if (!property->tie(SGRawValuePointer<int>(pointer), useDefault))
cerr << "Failed to tie property " << name << " to a pointer" << endl;
else {
tied_properties.push_back(property);
if (FGJSBBase::debug_lvl & 0x20) cout << name << endl;
}
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void FGPropertyManager::Tie (const string &name, long *pointer,
bool useDefault )
{
SGPropertyNode* property = root->getNode(name.c_str(), true);
if (!property) {
cerr << "Could not get or create property " << name << endl;
return;
}

if (!property->tie(SGRawValuePointer<long>(pointer), useDefault))
cerr << "Failed to tie property " << name << " to a pointer" << endl;
else {
tied_properties.push_back(property);
if (FGJSBBase::debug_lvl & 0x20) cout << name << endl;
}
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void FGPropertyManager::Tie (const string &name, float *pointer,
bool useDefault )
{
SGPropertyNode* property = root->getNode(name.c_str(), true);
if (!property) {
cerr << "Could not get or create property " << name << endl;
return;
}

if (!property->tie(SGRawValuePointer<float>(pointer), useDefault))
cerr << "Failed to tie property " << name << " to a pointer" << endl;
else {
tied_properties.push_back(property);
if (FGJSBBase::debug_lvl & 0x20) cout << name << endl;
}
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void FGPropertyManager::Tie (const string &name, double *pointer, bool useDefault)
{
SGPropertyNode* property = root->getNode(name.c_str(), true);
if (!property) {
cerr << "Could not get or create property " << name << endl;
return;
}

if (!property->tie(SGRawValuePointer<double>(pointer), useDefault))
cerr << "Failed to tie property " << name << " to a pointer" << endl;
else {
tied_properties.push_back(property);
if (FGJSBBase::debug_lvl & 0x20) cout << name << endl;
}
}

} // namespace JSBSim
175 changes: 53 additions & 122 deletions src/input_output/FGPropertyManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -424,58 +424,8 @@ class FGPropertyManager
*/
void Unbind (void);

// Templates cause ambiguity here

/**
* Tie a property to an external bool variable.
*
* The property's value will automatically mirror the variable's
* value, and vice-versa, until the property is untied.
*
* @param name The property name to tie (full path).
* @param pointer A pointer to the variable.
* @param useDefault true if any existing property value should be
* copied to the variable; false if the variable should not
* be modified; defaults to true.
*/
void
Tie (const std::string &name, bool *pointer, bool useDefault = true);


/**
* Tie a property to an external int variable.
*
* The property's value will automatically mirror the variable's
* value, and vice-versa, until the property is untied.
*
* @param name The property name to tie (full path).
* @param pointer A pointer to the variable.
* @param useDefault true if any existing property value should be
* copied to the variable; false if the variable should not
* be modified; defaults to true.
*/
void
Tie (const std::string &name, int *pointer, bool useDefault = true);


/**
* Tie a property to an external long variable.
*
* The property's value will automatically mirror the variable's
* value, and vice-versa, until the property is untied.
*
* @param name The property name to tie (full path).
* @param pointer A pointer to the variable.
* @param useDefault true if any existing property value should be
* copied to the variable; false if the variable should not
* be modified; defaults to true.
*/
void
Tie (const std::string &name, long *pointer, bool useDefault = true);


/**
* Tie a property to an external float variable.
* Tie a property to an external variable.
*
* The property's value will automatically mirror the variable's
* value, and vice-versa, until the property is untied.
Expand All @@ -486,47 +436,22 @@ class FGPropertyManager
* copied to the variable; false if the variable should not
* be modified; defaults to true.
*/
void
Tie (const std::string &name, float *pointer, bool useDefault = true);

/**
* Tie a property to an external double variable.
*
* The property's value will automatically mirror the variable's
* value, and vice-versa, until the property is untied.
*
* @param name The property name to tie (full path).
* @param pointer A pointer to the variable.
* @param useDefault true if any existing property value should be
* copied to the variable; false if the variable should not
* be modified; defaults to true.
*/
void
Tie (const std::string &name, double *pointer, bool useDefault = true);

//============================================================================
//
// All of the following functions *must* be inlined, otherwise linker
// errors will result
//
//============================================================================

/* template <class V> void
Tie (const std::string &name, V (*getter)(), void (*setter)(V) = 0,
bool useDefault = true);
template <class V> void
Tie (const std::string &name, int index, V (*getter)(int),
void (*setter)(int, V) = 0, bool useDefault = true);
template <class T, class V> void
Tie (const std::string &name, T * obj, V (T::*getter)() const,
void (T::*setter)(V) = 0, bool useDefault = true);
template <typename T> void
Tie (const std::string &name, T *pointer, bool useDefault = true)
{
SGPropertyNode* property = root->getNode(name.c_str(), true);
if (!property) {
cerr << "Could not get or create property " << name << endl;
return;
}

template <class T, class V> void
Tie (const std::string &name, T * obj, int index,
V (T::*getter)(int) const, void (T::*setter)(int, V) = 0,
bool useDefault = true); */
if (!property->tie(SGRawValuePointer<T>(pointer), useDefault))
cerr << "Failed to tie property " << name << " to a pointer" << endl;
else {
tied_properties.push_back(property);
if (FGJSBBase::debug_lvl & 0x20) cout << name << endl;
}
}

/**
* Tie a property to a pair of simple functions.
Expand All @@ -545,26 +470,27 @@ class FGPropertyManager
* discarded; defaults to true.
*/

template <class V> inline void
Tie (const std::string &name, V (*getter)(), void (*setter)(V) = 0, bool useDefault = true)
template <typename T> void
Tie (const std::string &name, T (*getter)(), void (*setter)(T) = nullptr,
bool useDefault = true)
{
SGPropertyNode* property = root->getNode(name.c_str(), true);
if (!property) {
std::cerr << "Could not get or create property " << name << std::endl;
return;
}

if (!property->tie(SGRawValueFunctions<V>(getter, setter), useDefault))
std::cerr << "Failed to tie property " << name << " to functions" << std::endl;
if (!property->tie(SGRawValueFunctions<T>(getter, setter), useDefault))
std::cerr << "Failed to tie property " << name << " to functions"
<< std::endl;
else {
if (setter == 0) property->setAttribute(SGPropertyNode::WRITE, false);
if (getter == 0) property->setAttribute(SGPropertyNode::READ, false);
if (!setter) property->setAttribute(SGPropertyNode::WRITE, false);
if (!getter) property->setAttribute(SGPropertyNode::READ, false);
tied_properties.push_back(property);
if (FGJSBBase::debug_lvl & 0x20) std::cout << name << std::endl;
}
}


/**
* Tie a property to a pair of indexed functions.
*
Expand All @@ -580,29 +506,31 @@ class FGPropertyManager
* @param getter The getter function, or 0 if the value is unreadable.
* @param setter The setter function, or 0 if the value is unmodifiable.
* @param useDefault true if the setter should be invoked with any existing
* property value should there be one; false if the old value should be
* discarded; defaults to true.
* property value should there be one; false if the old value should
* be discarded; defaults to true.
*/
template <class V> inline void Tie (const std::string &name, int index, V (*getter)(int),
void (*setter)(int, V) = 0, bool useDefault = true)
template <typename T> void
Tie (const std::string &name, int index, T (*getter)(int),
void (*setter)(int, T) = nullptr, bool useDefault = true)
{
SGPropertyNode* property = root->getNode(name.c_str(), true);
if (!property) {
std::cerr << "Could not get or create property " << name << std::endl;
return;
}

if (!property->tie(SGRawValueFunctionsIndexed<V>(index, getter, setter), useDefault))
std::cerr << "Failed to tie property " << name << " to indexed functions" << std::endl;
if (!property->tie(SGRawValueFunctionsIndexed<T>(index, getter, setter),
useDefault))
std::cerr << "Failed to tie property " << name << " to indexed functions"
<< std::endl;
else {
if (setter == 0) property->setAttribute(SGPropertyNode::WRITE, false);
if (getter == 0) property->setAttribute(SGPropertyNode::READ, false);
if (!setter) property->setAttribute(SGPropertyNode::WRITE, false);
if (!getter) property->setAttribute(SGPropertyNode::READ, false);
tied_properties.push_back(property);
if (FGJSBBase::debug_lvl & 0x20) std::cout << name << std::endl;
}
}


/**
* Tie a property to a pair of object methods.
*
Expand All @@ -619,12 +547,12 @@ class FGPropertyManager
* @param setter The object's setter method, or 0 if the value is
* unmodifiable.
* @param useDefault true if the setter should be invoked with any existing
* property value should there be one; false if the old value should be
* discarded; defaults to true.
* property value should there be one; false if the old value should
* be discarded; defaults to true.
*/
template <class T, class V> inline void
template <class T, class V> void
Tie (const std::string &name, T * obj, V (T::*getter)() const,
void (T::*setter)(V) = 0, bool useDefault = true)
void (T::*setter)(V) = nullptr, bool useDefault = true)
{
SGPropertyNode* property = root->getNode(name.c_str(), true);
if (!property) {
Expand All @@ -633,10 +561,11 @@ class FGPropertyManager
}

if (!property->tie(SGRawValueMethods<T,V>(*obj, getter, setter), useDefault))
std::cerr << "Failed to tie property " << name << " to object methods" << std::endl;
std::cerr << "Failed to tie property " << name << " to object methods"
<< std::endl;
else {
if (setter == 0) property->setAttribute(SGPropertyNode::WRITE, false);
if (getter == 0) property->setAttribute(SGPropertyNode::READ, false);
if (!setter) property->setAttribute(SGPropertyNode::WRITE, false);
if (!getter) property->setAttribute(SGPropertyNode::READ, false);
tied_properties.push_back(property);
if (FGJSBBase::debug_lvl & 0x20) std::cout << name << std::endl;
}
Expand All @@ -658,24 +587,26 @@ class FGPropertyManager
* @param getter The getter method, or 0 if the value is unreadable.
* @param setter The setter method, or 0 if the value is unmodifiable.
* @param useDefault true if the setter should be invoked with any existing
* property value should be; false if the old value should be
* discarded; defaults to true.
* property value should there be one; false if the old value should
* be discarded; defaults to true.
*/
template <class T, class V> inline void
template <class T, class V> void
Tie (const std::string &name, T * obj, int index, V (T::*getter)(int) const,
void (T::*setter)(int, V) = 0, bool useDefault = true)
void (T::*setter)(int, V) = nullptr, bool useDefault = true)
{
SGPropertyNode* property = root->getNode(name.c_str(), true);
if (!property) {
std::cerr << "Could not get or create property " << name << std::endl;
return;
}

if (!property->tie(SGRawValueMethodsIndexed<T,V>(*obj, index, getter, setter), useDefault))
std::cerr << "Failed to tie property " << name << " to indexed object methods" << std::endl;
if (!property->tie(SGRawValueMethodsIndexed<T,V>(*obj, index, getter, setter),
useDefault))
std::cerr << "Failed to tie property " << name
<< " to indexed object methods" << std::endl;
else {
if (setter == 0) property->setAttribute(SGPropertyNode::WRITE, false);
if (getter == 0) property->setAttribute(SGPropertyNode::READ, false);
if (!setter) property->setAttribute(SGPropertyNode::WRITE, false);
if (!getter) property->setAttribute(SGPropertyNode::READ, false);
tied_properties.push_back(property);
if (FGJSBBase::debug_lvl & 0x20) std::cout << name << std::endl;
}
Expand Down

0 comments on commit 9a01cea

Please sign in to comment.