0

I am writing a function that will load and save values into a .yaml file (depending on what the toggle input is; 'S' for save and 'L' for load). For some reason I am getting a Invalid initialization of non-const reference of type 'YAML::Node&' from an rvalue of type 'YAML::Node' error in the line:

YAML::Node& child = parent[*currentToken];

The solution I found online was to make it constant by adding the const keyword. However, like I said earlier, I need to be able to save value as well. Thus, I must be able to modify the node and cannot make it const. I am a bit lost as to what I should do now. My code takes in an iterator for the first node in the .yaml file and the last node. Here is my code:

bool ReadParameter(YAML::Node& parent,
        boost::tokenizer< boost::char_separator< char > >::iterator& currentToken,
        const boost::tokenizer< boost::char_separator< char > >::iterator& lastToken, float& value,
        char toggle) {

    /*
     * When we reach the last token, the distance between the iterators is 1. At this point we must
     * check to see if the token node exists in the yaml file. If it does store the value associated
     * with the token key in the variable `value` to load or store the value back into the yaml file to save.
     */
    if (distance(currentToken, lastToken) == 1) {
        if (parent[*(currentToken)].IsScalar()) {
            if (toggle == 'L') { // Load
                value = parent[*(currentToken)].as< float >();
            }
            else if (toggle == 'S') { // Save
                parent[*(currentToken)] = value;
            }
            return true;
        } else {
            printf("Key %s does not give a scalar value.\n", (*currentToken).c_str());
            return false;
        }
    }

    // If the node is a map, get it's child. Else, our path does not exist.
    if (parent.IsMap()) {
        YAML::Node& child = parent[*currentToken];

        // If there is no child node, return false
        if (child.IsNull()) {
            printf("There are no more child nodes.\n");
            return false;
        }

        // Iterate to the next token.
        return ReadParameter(child, ++currentToken, lastToken, value, toggle);
    } else {
        printf("Too many parameters, the parameter path is incorrect.\n");
        return false;
    }

}
Oktalist
  • 14,336
  • 3
  • 43
  • 63
jlcv
  • 1,688
  • 5
  • 21
  • 50

1 Answers1

1

YAML::Node is already a reference semantic type. There is no need to bind instances of YAML::Node to references. They are designed to be passed around by value, but behave like references. For example:

YAML::Node a = 42;
YAML::Node b = a;
b = 43; // both a and b now contain the value 43

parent[*currentToken] returns a YAML::Node by value and as such it can't be bound to a non-const lvalue reference, because that would mean binding to a temporary object.

So remove the &, this is way it is designed to be used:

YAML::Node child = parent[*currentToken];

And on the first line:

bool ReadParameter(YAML::Node parent,
Oktalist
  • 14,336
  • 3
  • 43
  • 63
  • Without testing it, how would you figure out if `YAML::Node` is already a reference semantic type? Do I have to look at how it is defined? If so which part specifies that? – jlcv Jan 27 '15 at 10:17
  • Actually, are you sure they will contain the same value? I just ran this: http://pastebin.com/D2vDuCQw. And b produces a different address than a. Also, b does not contain the key and value. – jlcv Jan 27 '15 at 11:04
  • Different address is as expected; they are different objects which both point to the same internal state. Show the code in which you tried to display the contents of b. – Oktalist Jan 27 '15 at 13:56
  • I tried this code: http://pastebin.com/stm5Xgee and I get a windows pop up that says the text.exe has stopped working. – jlcv Jan 27 '15 at 14:00
  • I think we've discovered an inconsistency in the API. I've reported it [here](https://code.google.com/p/yaml-cpp/issues/detail?id=271). I've edited the example code in my answer. – Oktalist Jan 27 '15 at 15:41