Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Returning empty json object from a function of type const json& ? #1205

Closed
DragonOsman opened this issue Aug 20, 2018 · 3 comments
Closed

Returning empty json object from a function of type const json& ? #1205

DragonOsman opened this issue Aug 20, 2018 · 3 comments

Comments

@DragonOsman
Copy link

As the title says, I need to return an empty JSON object from a function of type const json&. This is the function:

const json &cache_storage::query(const std::tuple<std::string, std::string, double> &query_data, const char *accesskey)
{
	auto found = m_cache.find(query_data);
	boost::beast::error_code ec;
	try
	{
		if (found == m_cache.end() || (std::chrono::steady_clock::now() - found->second.first) > m_duration)
		{
			std::string host{ "apilayer.net" }, api_endpoint{ "/api/convert" },
				key{ accesskey }, from{ std::get<0>(query_data) }, to{ std::get<1>(query_data) }, amount{ std::to_string(std::get<2>(query_data)) },
				target = api_endpoint + "?access_key=" + accesskey + "&from=" + from + "&to=" + to + "&amount=" + amount,
				port{ "80" };
			int version = 11;

			// The io_context is required for all IO
			boost::asio::io_context ioc;

			// These objects perform our IO
			tcp::resolver resolver{ ioc };
			tcp::socket socket{ ioc };

			// Look up the domain name
			const auto results = resolver.resolve(host, port);

			// Make the connection on the IP address we get from a lookup
			boost::asio::connect(socket, results.begin(), results.end());

			// Set up an HTTP GET request message
			http::request<http::string_body> req{ http::verb::get, target, version };
			req.set(http::field::host, host);
			req.set(http::field::content_type, "application/json");
			req.set(http::field::accept, "application/json");
			req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);

			// Send the HTTP request to the remote host
			http::write(socket, req);

			// This buffer is used for reading and must be persisted
			boost::beast::flat_buffer buffer;

			// Declare a container to hold the response
			http::response<http::string_body> res;

			// Receive the HTTP response
			http::read(socket, buffer, res, ec);
			found = m_cache.insert_or_assign(found, query_data, std::make_pair(std::chrono::steady_clock::now(), json::parse(res.body())));
		}
		return found->second.second;
	}
	catch (const std::exception &e)
	{
		std::cerr << "Line 679: Error: " << e.what() << '\n';
	}
	catch (const boost::beast::error_code &ec)
	{
		std::cerr << "Line 683: Error: " << ec.message() << '\n';
	}
	return json{ "" };
}

But I'm getting this warning on it:

warning C4172: returning address of local variable or temporary

Basically I want to return a value indicating an error, but given the return type of the function it has to be a const json& object. The full code is in this Gist: https://gist.github.com/DragonOsman/d00ea7ec3d49c128ad7789293f156a09

@gregmarr
Copy link
Contributor

gregmarr commented Aug 20, 2018

This is not technically an issue with the library. The exact same thing would happen if you replaced json with std::string and just had the last line. The error message also tells you what exactly you're doing wrong. You're creating a temporary and returning it. This is bad because the temporary is destroyed before you get back to the caller. You need to return something that's going to outlast the function.

Some of the various options are:

  • Return an std::optional<json>
  • Return a const json * and return nullptr
  • Return a local const static:
    const static json empty;
    return empty;

@DragonOsman
Copy link
Author

I'm not making an issue to say there's something wrong with the library. I know it's something I did wrong. I'm just asking what I should do here to return an empty JSON object.

So returning a null const json * is also an option?

@DragonOsman
Copy link
Author

I just did return json{nullptr}; and it worked.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants