In the below code, I am taking requests from a client, put them together on a json object on my server class and sending it to a pusher(directly connected to a website, putting my data in there so I can search data easily)
The code is working perfectly fine, but my manager said that I need to pass json by reference in this code, and I have no idea what to do.
On Server Class:
grpc::Status RouteGuideImpl::PubEvent(grpc::ServerContext *context,
const events::PubEventRequest *request,
events::PubEventResponse *response){
for(int i=0; i<request->event_size();i++){
nhollman::json object;
auto message = request->events(i);
object["uuid"]=message.uuid();
object["topic"]=message.type();
pusher.jsonCollector(obj);
}
...
}
On Pusher Class:
private:
nholmann::json queue = nlohmann::json::array();
public:
void Pusher::jsonCollector(nlohmann::json dump){
queue.push_back(dump);
}
void Pusher::curlPusher(){
std::string str = queue.dump();
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, str.data());
...
}
As much as I understand, I need to send the json object by reference. How can I do that?
The simple answer is to change
void Pusher::jsonCollector(nlohmann::json dump)
to
void Pusher::jsonCollector(const nlohmann::json& dump)
(note that if this is inside the class then Pusher:: is a non-standard visual studio extension).
This will reduce the number of times the object is copied from 2 to 1 however you can avoid the copy completely by using std::move:
void Pusher::jsonCollector(nlohmann::json dump){
queue.push_back(std::move(dump));
}
And call it with:
pusher.jsonCollector(std::move(obj));
If you want to enforce this behaviour to ensure that callers of jsonCollector always use std::move you can change jsonCollector to:
void Pusher::jsonCollector(nlohmann::json&& dump){
queue.push_back(std::move(dump));
}
Well, references are one of the many, many features, that distinguishes C from C++.
In other languages, like python or java, when you pass an object (not basic types) to a function and change it there, it is changed in the caller entity as well. In these languages, you don't have pointers, but you need to pass the object, not a copy.
That's what you have with references in C++. They are used like value types, but they are no copy.
Pointers can be nullptr (or NULL in C), references cannot. The address a pointer points to can be changed (assigned), you cannot change what object a reference refers to.
Have a look at this https://en.cppreference.com/w/cpp/language/reference for more information.
Related
I am not sure if I can produce a compile-able example because my issue is a call to a third party library so its difficult to see what is happening (unless you have RTI DDS installed). But I will try to make it as complete an example as I can:
I am using RTI DDS library with C++11. Here is a code snippet that would work:
#include <dds/dds.hpp> // the RTI libs
int main()
{
dds::domain::DomainParticipant participant(0); // 0 is domain_id
dds::topic::Topic<MyTopic> topic(participant, "example");
dds::sub::DataReader<MyTopic> *reader = new dds::sub::DataReader<MyTopic>(dds::sub::Subscriber(participant), topic);
// Now pass the dereferenced reader pointer to the status condition c'tor
dds::core::cond::StatusCondition condition(*reader);
return 0;
}
So this is just a snippet that works, but I would like to have my status condition to be a member variable so that it lives within a class scope and I can use it in various places. I also want to use smart pointers for their auto-destruction properties.
But if I use a unique_ptr instead of a raw pointer I get an error - so I assumed this was because unique_ptr has some protection from being copied or such.
So I thought maybe a shared pointer might be useable here:
#include <dds/dds.hpp> // the RTI libs
int main()
{
dds::domain::DomainParticipant participant(0); // 0 is domain_id
dds::topic::Topic<MyTopic> topic(participant, "example");
std::shared_ptr<dds::sub::DataReader<MyTopic>> shared_ptr_reader = std::shared_ptr<dds::sub::DataReader<MyTopic>>(new dds::sub::DataReader<MyTopic>(dds::sub::Subscriber(participant), topic));
// Now pass the dereferenced reader pointer to the status condition c'tor
dds::core::cond::StatusCondition condition(*shared_ptr_reader); // <-- Crashes here
return 0;
}
This crashes - throws a low-level RTI exceptpion, the stack trace is really not helping me since its deep in the guts of the RTI library :(
The API for the constructor of StatusCondition is here:
dds::core::cond::StatusCondition::StatusCondition ( const dds::core::Entity & entity )
inline
Obtains a reference to the StatusCondition in an entity. Parameters.
entity The Entity whose status condition we're getting a reference to.
There is exactly one StatusCondition per Entity and one Entity per
StatusCondition. NoteThis constructor doesn't create a new Condition.
It obtains a reference to the StatusCondition that each Entity owns.
You can use this constructors as many times as needed to obtain a
reference to the same StatusCondition.
So it looks like it is referencing some internal of the DataReader that is pointed to by the shared_ptr.
So my question is, is there any reason that a shared_ptr would not work in this case compared to a raw pointer?
How can I calculate a hash/checksum/fingerprint of an object in c++?
Requirements:
The function must be 'injective'(*). In other words, there should be no two different input objects, that return the same hash/checksum/fingerprint.
Background:
I am trying to come up with a simple pattern for checking whether or not an entity object has been changed since it was constructed. (In order to know which objects need to be updated in the database).
Note that I specifically do not want to mark the object as changed in my setters or anywhere else.
I am considering the following pattern: In short, every entity object that should be persisted, has a member function "bool is_changed()". Changed, in this context, means changed since the objects' constructor was called.
Note: My motivation for all this is to avoid the boilerplate code that comes with marking objects as clean/dirty or doing a member by member comparison. In other words, reduce risk of human error.
(Warning: psudo c++ code ahead. I have not tried compiling it).
class Foo {
private:
std::string my_string;
// Assume the "fingerprint" is of type long.
long original_fingerprint;
long current_fingerprint()
{
// *** Suggestions on which algorithm to use here? ***
}
public:
Foo(const std::string& my_string) :
my_string(my_string)
{
original_fingerprint = current_fingerprint();
}
bool is_changed() const
{
// If new calculation of fingerprint is different from the one
// calculated in the constructor, then the object has
// been changed in some way.
return current_fingerprint() != original_fingerprint;
}
void set_my_string(const std::string& new_string)
{
my_string = new_string;
}
}
void client_code()
{
auto foo = Foo("Initial string");
// should now return **false** because
// the object has not yet been changed:
foo.is_changed();
foo.set_my_string("Changed string");
// should now return **true** because
// the object has been changed:
foo.is_changed();
}
(*) In practice, not necessarily in theory (like uuids are not unique in theory).
You can use the CRC32 algorithm from Boost. Feed it with the memory locations of the data you want to checksum. You could use a hash for this, but hashes are cryptographic functions intended to guard against intentional data corruption and are slower. A CRC performs better.
For this example, I've added another data member to Foo:
int my_integer;
And this is how you would checksum both my_string and my_integer:
#include <boost/crc.hpp>
// ...
long current_fingerprint()
{
boost::crc_32_type crc32;
crc32.process_bytes(my_string.data(), my_string.length());
crc32.process_bytes(&my_integer, sizeof(my_integer));
return crc32.checksum();
}
However, now we're left with the issue of two objects having the same fingerprint if my_string and my_integer are equal. To fix this, we should include the address of the object in the CRC, since C++ guarantees that different objects will have different addresses.
One would think we can use:
process_bytes(&this, sizeof(this));
to do it, but we can't since this is an rvalue and thus we can't take its address. So we need to store the address in a variable instead:
long current_fingerprint()
{
boost::crc_32_type crc32;
void* this_ptr = this;
crc32.process_bytes(&this_ptr, sizeof(this_ptr));
crc32.process_bytes(my_string.data(), my_string.length());
crc32.process_bytes(&my_integer, sizeof(my_integer));
return crc32.checksum();
}
Such a function does not exist, at least not in the context that you are requesting.
The STL provides hash functions for basic types (std::hash), and you could use these to implement a hash function for your objects using any reasonable hashing algorithm.
However, you seem to be looking for an injective function, which causes a problem. Essentially, to have an injective function, it would be necessary to have an output of size greater or equal to that of the object you are considering, since otherwise (from the pigeon hole principle) there would be two inputs that give the same output. Given that, the most sensible option would be to just do a straight-up comparison of the object to some sort of reference object.
I have a function that stores the value of an argument to an std::vector<v8::Local<v8::Value>> property of a C++ class exposes as an ObjectWrap like this:
NAN_METHOD(MyObject::Write) {
MyObject* obj = Nan::ObjectWrap::Unwrap<MyObject>(info.This());
obj->data.push_back(info[0]);
}
However, when I try to read back the value from another C++ function, the value is lost, and becomes undefined.
I'm passing a number to MyObject::Write, and I can confirm info[0]->IsNumber() returns true before pushing it to the vector, however when reading it back, the value it not a number, and in fact returns false for all the types I tested using Is<Type> methods from v8::Value, but still returns true for BooleanValue().
My guess is that the variable is being garbage collected after MyObject::Write returns, however I have no idea how to prevent this from happening.
I'm currently trying to initialise the value as a Persistent value. I tried the following attempts without success:
Nan::CopyablePersistentTraits<v8::Value>::CopyablePersistent p;
Nan::Persistent<v8::Value> persistent(info[0]);
Nan::CopyablePersistentTraits::Copy(persistent, p);
And:
v8::Isolate *isolate = info.GetIsolate();
v8::Persistent<v8::Value, v8::CopyablePersistentTraits<v8::Value>> persistent(isolate, info[0]);
But getting tons of C++ errors.
I was running into problems untangling this mess myself. There's a lot of template stuff going on here that we both missed. Here was the solution I found most readable:
// Define the copyable persistent
v8::CopyablePersistentTraits<v8::Value>::CopyablePersistent p;
// Create the local value
auto val = v8::Local<v8::Value>::New(
v8::Isolate::GetCurrent(), //< Isolate required
v8::Integer::New(v8::Isolate::GetCurrent(), v) //< Isolate required
);
// Reset() is a TEMPLATE FUNCTION, you have to template it with the same
// template type parameter as the v8::Local you are passing
p.Reset<v8::Value>(v8::Isolate::GetCurrent(), val); //< Isolate required
By "info" I assume you are referring to a v8::FunctionCallbackInfo reference. If so the above code would collapse to the following:
void SomeFunc(v8::FunctionCallbackInfo<v8::Value>& info) {
v8::CopyablePersistentTraits<v8::Value>::CopyablePersistent p;
p.Reset<v8::Value>(info[0]);
}
Because the persistent is now copyable you can do things like store it inside a standard library container. This was my use case. This is an example of storing a value in a vector:
std::vector<v8::CopyablePersistentTraits<v8::Value>::CopyablePersistent> vect;
void AccumulateData(v8::FunctionCallbackInfo<v8::Value>& info) {
v8::CopyablePersistentTraits<v8::Value>::CopyablePersistent p;
p.Reset<v8::Value>(info[0]);
vect.push_back(p);
}
I hope this helps someone out there.
If you plan on storing v8 values in C++, you need to make them persistent instead of local so they're independent of handle scope and not garbage-collected when the handle scope is released.
Nan has version-independant wrappers for v8::Persistent and Co. Because of using inside std::vector<>, you'll also need to initialize Nan::Persistent with Nan::CopyablePersistentTraits so it becomes copyable (or make an own reference-counted container for it).
I'm writing macros for debugging system
I have an overloaded chained operator <<(MessageAssembler& target,message_type msg)
(message_type) is a template parameter for the operator
It adds msg to target's inner variable of type QTextStream.
The operator +=(MessageAssembler& result) of MessageAssembler passes result's stream to function which processes it based on parameters of result.
I want to do something like this:
#define FATAL(facility) NLog::assembler+=MessageAssembler(Log::fatal_sev,facility)<< __FILE__<<":"<<__LINE__
(NLog::assembler is a static variable of type MessageAssembler)
It should determine output's facility, allow a user to add its own message to output by using
FATAL(some_facility)<<"custom message"<<ObjectWhichCanBePassedToQTextStream()<<AnotherObject();
But MessageAssembler(Log::fatal_sev,facility) produces a reference to temporary error.
This
MessageAssembler& MessageAssembler::get_instance(Log::Severity _msg_sev,Log::Facility _msg_fac)
{
MessageAssembler tmp(_msg_sev,_msg_fac);
return tmp;
}
will return a reference to a non-existing object;
This
MessageAssembler& MessageAssembler::get_instance(Log::Severity _msg_sev,Log::Facility _msg_fac)
{
return new MessageAssembler tmp(_msg_sev,_msg_fac);
}
will cause a memory leak
This
QScopedPointer<MessageAssembler> MessageAssembler::get_instance(Log::Severity _msg_sev,Log::Facility _msg_fac)
{
return QScopedPointer<MessageAssembler>(new MessageAssembler tmp(_msg_sev,_msg_fac));
}
will not work because QScopedPointer can't be passed by value
I'm not sure if storing second static variable MessageAssembler chain_starter; is thread-safe.
I have not only FATAL macro, so the program won't be always terminated after the call.
How can i return a reference to a new MessageAssembler?
EDIT: My problem was solved by installing a third-party library for smart pointer, namely, yasper. The general solution is proposed by πάντα ῥεῖ.
The most concise answer is:
Don't do it using raw pointers! Use the c++ smart pointer features instead.
The most straightforward implementation seems to be, creating a std::unique_ptr<MessageAssembler> instance and return this one. The calling client will receive ownership of the created instance and it will be deleted automatically, as soon that reference goes out of scope.
I am coming from the C++ world and i want to do some simple stuff with Actionscript 3.0.
Have search around this site and google and haven't found a universally accepted way to do so. I will give you the C++ code of the analogous of what I am trying to do in Actionscript 3.0.
Pass by reference:
void somefunction (string &passvariable);
Create instance of, deep copy:
string something;
string somethingelse;
something = "randomtext";
somethingelse = something;
Pass by reference
Every object is passed by reference. As far as I know, there are no explicit & address of or * dereference operators. Actionscript is a higher level language than that.
Primitive types (and Strings are primitive - see link) are Immutable in Actionscript, so pass by value / pass by reference are effectively the same.
Deep Copy / Instance of
ObjectUtil.clone / ObjectUtil.copy will create sometimes-deep copies of Objects, if you're working in Flex. I usually don't rely on it for anything deep, however. In most cases you will want to create your own clone style method to create a deep copy.
A generic, flexible clone method can be found here
The rules for pass as reference are different for simple data types like string and number than they are for objects and complex data types.
If you are passing a string to a function, it creates a copy, leaving the original untouched.
So to pass by reference, try creating an object:
var str:Object = {string:"foo"};
passByref(str);
trace(str.string);
private function passByref(str:Object):void
{
str.string = str.string + "bar";
trace("inside", str);
}
As for deep object cloning, this works great:
package
{
import flash.utils.ByteArray;
public class DeepCopyUtil
{
public static function clone (source : Object) : *
{
var array : ByteArray = new ByteArray ();
array.writeObject (source);
array.position = 0;
return array.readObject ();
}
}
}
Credit where credit is due:
http://cookbooks.adobe.com/post_How_to_create_deep_copies_of_objects_and_arrays-19261.html
In Actionscript you have to define all things with function, var or const.
You should define the (return type) after the variable name, like var:String
Creating a function
function someFunction (var:String):void
{
}
Copy a string
var something:String;
var somethingElse:String;
something = "randomtext";
somethingelse = something;