Vector and var and ReferenceCountedObject?


#1

Is that reasonable to use a vector in a var ?
I don’t find any way of retrieving the vector once it is (may be) saved in the var.
I created a PtVector class derived from ReferenceCountedObject. I then instanciate such an object, create a DynamicObject from this, then create a var from this last one.
The error shown at the print line is:
“no member named getVector() in ReferenceCountedObject”,
so I suppose it does not refer to the proper PtVector object that was intended at first.

The code resumed looks like this :
PtVector::RefCountedPointVectorPointer pv = new PtVector();
DynamicObject* obj = new DynamicObject();
obj->setProperty(“vector”, &pv);
var toto (obj);
std::cout << “var content : " << toto[“vector”].getObject()->getVector() << “\n”;

The class PointVector looks like this :
class PtVector : public ReferenceCountedObject
{
public:
PtVector()
{
vectorOfPoints = new std::vector<Point>;
typedef ReferenceCountedObjectPtr RefCountedPointVectorPointer;
}

std::vector<Point<int>> getVector()
{
    return *vectorOfPoints;
}
typedef ReferenceCountedObjectPtr<PtVector> RefCountedPointVectorPointer;
std::vector<Point<int>> *vectorOfPoints;

};


#2

The code you shared is entirely questionable, so I don’t even know where to start. What’s your goal - to have a reference counted vector? Or the inverse, storing a vector in a var? If the latter, know that var is only compatible with select types: primitives, and some JUCE classes.

Also, why are you allocating a vector on the heap?!


#3

I think you have to dynamically cast your ReferenceCountedObject to the PtVector class:

if (PtVectorPtr vector_object = dynamic_cast<PtVector*> (obj ["vector"].getObject()) {
    std::cout << "var content : ";
    for (auto elem : vector_object->getVector())
        std::cout << elem;
    std::cout << std::endl;
}

N.B., if you indent your code by four spaces it will display nicely…


#4

…Or you can enclose your code in triple backticks (on their own line):```


#5

Hope I can explain:
I tried to store a ReferenceCountedObject in a var because the doc says “A var object can hold a range of simple primitive values, strings, or any kind of ReferenceCountedObject.” So may be I don’t understand well what a ReferenceCountedObject is when I want to create a reference-counted vector. The idea came first when trying to store a vector in a ValueTree. May be this is also very questionable, but I don’t see why. Concerning the heap, I am just trying things out, so it’s not a real concern right now.
Thanks


#6

But surely you do know that allocating a std::vector on the heap doesn’t make much sense? The data is already internally heap allocated and the vector object just keeps track of some pointers. By heap allocating it you just risk losing all the benefits of using a nice C++ wrapper for the memory operations.

Also, for Juce based code you might want to consider using Juce’s Array class instead, although I’ve personally ended up using std::vectors too, especially if I don’t have to interact with the Juce API.


#7

You can wrap a vector into a ReferenceCountedObject, just as you did. But

  1. there will be no serialisation for custom objects in the var. If you write it to JSON, they just don’t show up, and they are not read back
  2. there is already the possibility to store an array of vars in the DynamicObject. This will write and parse to JSON

#8

Great advice, thanks!


#9

Anyway, what are your thoughts about this idea of storing vectors in a valueTree ?


#10

well, first var != ValueTree
And it really depends, what you want to achieve:

  1. Is this only on runtime, or do you need to save that data to a file
  2. does it need to be interchangeable with other software? var = good for JSON, ValueTree = good for XML
  3. What kind is the data? samples, indices, phone numbers?
  4. Is it much data? do you need fast access? does it need to be hierarchical in any way?

Sorry, but there is no short answer I guess…


#11

The biggest data so far would be arrays of integers representing pixel points (one y for each x of the component width). I’d like to be able to save it as XML, and most of all I’d like this array to be registered as undoable, which explains also the choice for ValueTree.


#12

That’s a good bit of info. I guess what’s left is what Daniel asked here:

To add to this I’d ask one more question:
• How often will the data change?

The reason for this is that I’d probably store it as a String and then parse it back to some kind of array when you need to access it. However, if you need fast access, you might want to create a custom VariantConverter so you can store it in a CachedValue.

There are other options such as storing as a memory block which may reduce parse time (but introduce some base64 encoding time) or you could just add each point as a new ValueTree child with two properties?
It really depends on exactly how this data is going to be used…


#13

In that case I would agree, ValueTree (not var) is the thing to go. Have a look at the Projucer, if you create a GuiComponent and open the Code tab, you will see in the comment a XML representation of the components. You can take that as inspiration.

This will serialise to a ValueTree using the ComponentBuilder


#14

Like this kind of things ? :
s 258 252 l 576 448 l 64 256 x
So I assume it would be possible to write/read a ValueTree conatining 1400 values in a reasonable time ?


#15

Thanks very much. That gives a lot of perspectives. I didn’t think about the string conversion. May be it would fit with the use case of drawing a line, modifying it and just updating the vector (in a String) when mouseUp() ?


#16

Yeah, you can do this sort of thing lazily to avoid constant property changes and listener callbacks etc. For example, in Waveform we flush the plugin states to the tree only when a save happens (e.g. not constantly when a parameter changes).