Search code examples
c++jsoncpp

Why does this call to Json::Value::append with a pointer compile?


Yesterday I came across a function like this in my team's code, using the jsoncpp library:

#include <json/value.h>

Json::Value makeList() {
  Json::Value list(Json::arrayValue);
  list.append(new Json::Value(true));
  return list;
}

It came to my attention because using new in the call to list.append leaks some memory, which can be fixed by simply dropping new. However, in debugging this I realized that Json::Value::append takes either a const Json::Value& or a Json::Value&&. C++ does not implicitly convert pointers to references, so a Json::Value* should not be implicitly converted into either of these.

To confirm this, I wrote my own short example:

#include <iostream>

class Foo {
public:
    int x = 4;
};

void printValue(const Foo& f) { std::cout << "The value is " << f.x << ".\n"; }
void printValue(Foo&& f)      { std::cout << "The value is " << f.x << ".\n"; }

int main() {
    printValue(new Foo());
}

And indeed, this results in a compilation error:

own-example.cpp:12:5: error: no matching function for call to 'printValue'
    printValue(new Foo());
    ^~~~~~~~~~
own-example.cpp:8:6: note: candidate function not viable: no known conversion from 'Foo *' to 'const Foo' for 1st argument; dereference the argument with *
void printValue(const Foo& f) { std::cout << "The value is " << f.x << ".\n"; }
     ^
own-example.cpp:9:6: note: candidate function not viable: no known conversion from 'Foo *' to 'Foo' for 1st argument; dereference the argument with *
void printValue(Foo&& f)      { std::cout << "The value is " << f.x << ".\n"; }
     ^

So, why does the code I found calling Json::Value::append compile, while the toy example does not?


Solution

  • Json::Value(new Json::Value()) compiles because