I am quite new to C++ but am familiar with a few other languages.
I would like to use a data type similar to a Java ArrayList, an Objective-c NSMutableArray or a Python array, but in C++. The characteristics I am looking for are the possibility to initialize the array without a capacity (thus to be able to add items gradually), and the capability to store multiple datatypes in one array.
To give you details of what I want it for is to read data from different tables of a mysql db, without knowing the number of fields in the table, and being able to move this data around. My ideal data type would allow me to store something like this:
idealArray = [Bool error,[string array],[string array]];
where the string arrays may have different sizes, from 1 to 20 in size (relatively small).
I don't know if this is possible in C++, any help appreciated, or links towards good ressources.
Thanks
The standard dynamically sized array in C++ is std::vector<>. Homogeneous containers doesn't exist unless you introduce indirection, for this you can use either boost::variant or boost::any depending on your needs.
You may use structure or class to store (named) multiple data types together, such as:
class Record
{
bool _error;
vector<string> _v1;
vector<string> _v2;
};
vector<Record> vec;
or std::tuple to store (unnamed) multiple data types, e.g.
vector<tuple<bool, vector<string>, vector<string> > > vec;
I would suggest using a std::vector from the STL. However, note that C++ does not have a container that can contain multiple data types. There are multiple ways to simulate this behaviour though:
Derive all the "types" that you want to store from a certain "Base_type". Then store the items in the vector as std::vector<Base_type*>, but then you would need to know which item is where and the type to (dynamic)cast to, if the "types" are totally different.
Use something like std::vector<boost::any> from the boost library (but noticing that you are new to C++, that might be overkill).
In fact, the question you need to ask is, why do you want to store unrelated "types" in an "array" in the first place? and if they are related, then "how"? this will guide you in desgining a decent "Base_type" for the "types".
And finally, in short, C++ does not have homogenous array-like structures that can contain unrelated data types.
You could try to use an std::vector<boost::any> (documentation here).
Related
I most often work with python and therefore I'm used to being able to put a bool and integer in a single list. I realize that C++ has a different paradigm, however, I imagine that there is a workaround to this issue. Ideally I want a vector that could contain data that looks like {1, 7, true, 8, false, true, 9}. So this vector would have to be defined with syntax like (vector int bool intBoolsVec), however, I realize that isn't proper syntax.
I see that some people suggest using variant that was introduced in C++17, is this the best solution? Seems like this would be a common problem if C++ doesn't easily allow you to work with heterogenous containers, even if those containers are constrained to a couple defined types like a vector that only takes only ints and bools.
What is the easiest way to create a vector that contains both integers and booleans in C++? If someone could also provide me more insight on why C++ doesn't have an easy/obvious way to do this, that might help me better understand C++ as well.
My approach would probably be to create my own class, which does exactly what I want it to do. This might be your easiest solution, besides using std::any. Also, you could combine those by creating a custom array of std::any which only allows integers and booleans at certain entries for your example. This would be similar, but not equal to an array of std::variant. Also, In C++ you can store 2 types in a std::pair, if that fits your use-case.
I previously read of a structure or class in C++11 that allows saving two values as one, what its name?
For example, I want to save 1 and 2 together, I know it's easy to implement but if there is one already done why to implement mine :)
The traditional way of storing a number of values without naming them all is to use an array:
int arr[2] = {1, 2};
C++ being what it is, you have lots of other ways to do that. You could achieve something similar with the use of std::array, std::vector (or other STL containers), std::tuple, std::pair, new int[2], struct {int x, y;} elms;, or do something crazy like store 2 32bit values in a single 64bit integer. These are all suitable for different use cases depending on stuff like if the values you're trying to store have the same type, if you know how many of them you want to store at compile time, if the size is fixed, if you have a few of them or many of them, if you're trying to interface with C APIs and so on. I suggest you have a look at our C++ Book Guide and List.
Is it possible to programmatically create objects of structs and fill the fields, when you have a list of struct names and field values?
Say I have to read entry from (JSON)file and fill up my structs. I have value struct names and values but i want to code such that code will loop all structs and fill the in-memory data. may sound wierd, but is there a way?
Nope. The language feature you're looking for is called reflection, and C++ does not have it.
You could build up a std::map<std::string, SomeType> instead? If SomeType differs depending on the field, a boost::variant will allow you to store any of a number of types at any given time (it's basically a tagged union).
Or you could switch to Python. :)
Let me preface this with the statement that most of my background has been with functional programming languages so I'm fairly novice with C++.
Anyhow, the problem I'm working on is that I'm parsing a csv file with multiple variable types. A sample line from the data looks as such:
"2011-04-14 16:00:00, X, 1314.52, P, 812.1, 812"
"2011-04-14 16:01:00, X, 1316.32, P, 813.2, 813.1"
"2011-04-14 16:02:00, X, 1315.23, C, 811.2, 811.1"
So what I've done is defined a struct which stores each line. Then each of these are stored in a std::vector< mystruct >. Now say I want to subset this vector by column 4 into two vectors where every element with P in it is in one and C in the other.
Now the example I gave is fairly simplified, but the actual problem involves subsetting multiple times.
My initial naive implementation was iterate through the entire vector, creating individual subsets defined by new vectors, then subsetting those newly created vectors. Maybe something a bit more memory efficient would be to create an index, which would then be shrunk down.
Now my question is, is there a more efficient, in terms of speed/memory usage) way to do this either by this std::vector< mystruct > framework or if there's some better data structure to handle this type of thing.
Thanks!
EDIT:
Basically the output I'd like is first two lines and last line separately. Another thing worth noting, is that typically the dataset is not ordered like the example, so the Cs and Ps are not grouped together.
I've used std::partition for this. It's not part of boost though.
If you want a data structure that allows you to move elements between different instances cheaply, the data structure you are looking for is std::list<> and it's splice() family of functions.
I understand you have not per se trouble doing this but you seem to be concerned about memory usage and performance.
Depending on the size of your struct and the number of entries in the csv file it may be advisabe to use a smart pointer if you don't need to modify the partitioned data so the mystruct objects are not copied:
typedef std::vector<boost::shared_ptr<mystruct> > table_t;
table_t cvs_data;
If you use std::partition (as another poster suggested) you need to define a predicate that takes the indirection of the shared_ptr into accont.
I have a generic table class implemented in C++ that uses a shared_ptr< ptr_vector< vector<T> > > as its backing, where T is an arbitrary typename; the ptr_vector contains pointers to the vectors corresponding to the columns in the table. I decided to wrap the ptr_vector in a shared_ptr since the tables may contain many millions of rows, and the vectors containing data for each column in a ptr_vector for the same reason. (Please tell me if this can be improved.)
Implementing column-wise operations on this table is trivial, since I have access to the native iterator supplied by the vector. However, I also need the table to support row-wise operations: relatively mundane operations such as adding and removing rows should be supported, as well as the ability to use the STL algorithms with the table. Now, I have run across some design issues that I need some help to address:
It seems that implementing a custom iterator to conduct row-wise operations is necessary to accomplish what is describe above. Would boost::iterator_adaptor be the right way to go about doing this?
When the user adds rows to the table, I do not wish to impose a specific data structure upon the user -- how would I go about doing this? I am thinking of accepting iterators as parameters to the add_row() method.
If you think that I should be implementing this table structure differently, I am open to any suggestions that you may have for me. It was originally designed with the intent to store strings read from tab-delimited files containing hundreds of thousands of row entries.
Thank you very much for your help!
The Boost library has a container called multi_array which provides and n-dimensional dynamic array which can be accessed and manipulated along each dimension. This seems to be very similar to what you are trying to build, perhaps you could use it instead?