[CXX-963] How can I return a bsoncxx::document::element from a function? Created: 03/Jul/16  Updated: 08/Jan/24  Resolved: 13/Jul/16

Status: Closed
Project: C++ Driver
Component/s: Implementation
Affects Version/s: 3.0.1
Fix Version/s: None

Type: Task Priority: Trivial - P5
Reporter: George Thompson Assignee: Unassigned
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Windows 10
MS VS 2015
MongoDB 3.3.5
MongoDB C++11 Driver 3.0.1



 Description   

#include <bsoncxx/builder/stream/document.hpp>
#include <iostream>
 
bsoncxx::document::element return_element()
{
	auto build_doc = bsoncxx::builder::stream::document{};
	build_doc << "key_field" << "hello world";
	bsoncxx::document::element element_to_return = build_doc.view()["key_field"];
	// outputs: key_field hello world
	std::cout << element_to_return.key().to_string() << " " << element_to_return.get_utf8().value;
	return element_to_return;
}
 
int main()
{
	bsoncxx::document::element returned_element = return_element();
	// the next line causes a debug error at element.cpp
	// types::b_utf8 element::get_utf8() const {
	//	 BSONCXX_TYPE_CHECK(k_utf8);
	std::cout << returned_element.get_utf8().value;
    return 0;
}

The returned_element is "junk". Is there a way to preserve an element from a function?



 Comments   
Comment by Mira Carey [ 13/Jul/16 ]

It seems like you've found a work around for your issue in types::value (which is what that type was designed for).

If have more problems, feel free to open new issues.

Comment by Andrew Morrow (Inactive) [ 11/Jul/16 ]

therefore - That looks good, however I would like to call out one subtlety. The b_utf8 object that you are returning is a 'view' into a string. In this case, it works, because the string "string" is a string literal, and therefore outlives the function. Had you passed in std::string("string") however to the b_utf8 constructor it would have been a use-after-free. Just something to keep in mind.

Overall, there is no concept of an owned element in the driver. I think it might be possible to build such an abstraction, however. I'm envisioning a class that wraps a std::pair<std::shared_ptr<document::value>, bsoncxx::types::value>>, though I haven't completely thought it through.

Comment by George Thompson [ 04/Jul/16 ]

I ended up using bsoncxx::types::value to do what I want:

#include <bsoncxx/builder/stream/document.hpp>
#include <iostream>
#include <bsoncxx/types/value.hpp>
#include <bsoncxx/json.hpp>
 
bsoncxx::types::value return_element(bool which)
{
	bsoncxx::types::value bool_value_to_return{ bsoncxx::types::b_bool{true} };
	bsoncxx::types::value utf8_value_to_return{ bsoncxx::types::b_utf8{"string"} };
	return (which) ? bool_value_to_return : utf8_value_to_return;
}
int main()
{
	bsoncxx::types::value returned_element = return_element(true);
	auto build_doc = bsoncxx::builder::stream::document{};
	build_doc << "key_field" << returned_element;
 
	returned_element = return_element(false);
	build_doc << "2nd_key_field" << returned_element;
       // {   "key_field" : true, "2nd_key_field" : "string" }
	std::cout << bsoncxx::to_json(build_doc.view());
	return 0;
}

Comment by George Thompson [ 03/Jul/16 ]

I get that the element has a pointer to the document view that is no longer in scope. Is there a way, nonetheless, to return an element that I can then use to build a document in main? The objective is the value of the element could be one of several types. I previously used a BSONObj to achieve this.

Generated at Wed Feb 07 22:00:54 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.