Array of values within an ENUM? - c++

I have this code
enum type {NOTHING, SOMETHING, SOMETHINGELSE}
type *x;
At the moment I use x[765] == SOMETHING for example, How would I store other values for example
x[765] == SOMETHINGELSE;
x[765].position == 43.5;
x[765].somevar == 12;
I will apologize for my poor wording within my question im just starting out in C++, I know what I want i'm just not to sure on how to ask it.
Thanks.

It looks as if you're looking for a way to structure 'knowledge'; this is done with a struct or a class:
#include <vector>
struct Info {
enum thingness { nothing, something };
// 'member' variables
thingness howMuch;
int a_counter;
float position;
};
int main(){
Info object;
object.howMuch=Info::something;
object.a_counter=1;
object.position=5.4;
You can group these kinds of objects into a container - typically an std::vector:
// a container of InterestingValues
std::vector<Info> container(300);
container[299].howMuch=Info::nothing;
container[299].a_counter=4;
container[299].position = 3.3;
// or assign rightaway:
container[2] = object;
}

You will have to make yourself a more complex type:
struct type
{
enum flag_type
{
NOTHING, SOMETHING, SOMETHINGELSE
} flag;
double position;
int somevar;
};
and later have an array of this new type.

Get yourself a good book to learn from. A list of good books is available here: The Definitive C++ Book Guide and List
In C++, you are asking how to declare an array of structures. Try this:
struct type {
double position;
int somevar;
};
type *x;
x[765].position = 43.5;
x[765].somevar = 12;

An enum is a replaceable label basically for an int. You need to define a struct or a class.
struct type
{
float position ;
};
type var;
var.position = 3.4;

Your type enum would need to be a member of a class, along with the other fields. For example,
class MyType
{
public:
type t;
double position;
int somevar;
};
With an array of MyType instances
MyType *x;
you would then be able to do what you ask expect you would need to do
x[765].t = SOMETHINGELSE;
to assign to the enum.

Related

Save reference to void pointer in a vector during loop iteration

Guys I have a function like this (this is given and should not be modified).
void readData(int &ID, void*&data, bool &mybool) {
if(mybool)
{
std::string a = "bla";
std::string* ptrToString = &a;
data = ptrToString;
}
else
{
int b = 9;
int* ptrToint = &b;
data = ptrToint;
}
}
So I want to use this function in a loop and save the returned function parameters in a vector (for each iteration).
To do so, I wrote the following struct:
template<typename T>
struct dataStruct {
int id;
T** data; //I first has void** data, but would not be better to
// have the type? instead of converting myData back
// to void* ?
bool mybool;
};
my main.cpp then look like this:
int main()
{
void* myData = nullptr;
std::vector<dataStruct> vec; // this line also doesn't compile. it need the typename
bool bb = false;
for(int id = 1 ; id < 5; id++) {
if (id%2) { bb = true; }
readData(id, myData, bb); //after this line myData point to a string
vec.push_back(id, &myData<?>); //how can I set the template param to be the type myData point to?
}
}
Or is there a better way to do that without template? I used c++11 (I can't use c++14)
The function that you say cannot be modified, i.e. readData() is the one that should alert you!
It causes Undefined Behavior, since the pointers are set to local variables, which means that when the function terminates, then these pointers will be dangling pointers.
Let us leave aside the shenanigans of the readData function for now under the assumption that it was just for the sake of the example (and does not produce UB in your real use case).
You cannot directly store values with different (static) types in a std::vector. Notably, dataStruct<int> and dataStruct<std::string> are completely unrelated types, you cannot store them in the same vector as-is.
Your problem boils down to "I have data that is given to me in a type-unsafe manner and want to eventually get type-safe access to it". The solution to this is to create a data structure that your type-unsafe data is parsed into. For example, it seems that you inteded for your example data to have structure in the sense that there are pairs of int and std::string (note that your id%2 is not doing that because the else is missing and the bool is never set to false again, but I guess you wanted it to alternate).
So let's turn that bunch of void* into structured data:
std::pair<int, std::string> readPair(int pairIndex)
{
void* ptr;
std::pair<int, std::string> ret;
// Copying data here.
readData(2 * pairIndex + 1, ptr, false);
ret.first = *reinterpret_cast<int*>(ptr);
readData(2 * pairIndex + 2, ptr, true);
ret.second = *reinterpret_cast<std::string*>(ptr);
}
void main()
{
std::vector<std::pair<int, std::string>> parsedData;
parsedData.push_back(readPair(0));
parsedData.push_back(readPair(1));
}
Demo
(I removed the references from the readData() signature for brevity - you get the same effect by storing the temporary expressions in variables.)
Generally speaking: Whatever relation between id and the expected data type is should just be turned into the data structure - otherwise you can only reason about the type of your data entries when you know both the current ID and this relation, which is exactly something you should encapsulate in a data structure.
Your readData isn't a useful function. Any attempt at using what it produces gives undefined behavior.
Yes, it's possible to do roughly what you're asking for without a template. To do it meaningfully, you have a couple of choices. The "old school" way would be to store the data in a tagged union:
struct tagged_data {
enum { T_INT, T_STR } tag;
union {
int x;
char *y;
} data;
};
This lets you store either a string or an int, and you set the tag to tell you which one a particular tagged_data item contains. Then (crucially) when you store a string into it, you dynamically allocate the data it points at, so it will remain valid until you explicitly free the data.
Unfortunately, (at least if memory serves) C++11 doesn't support storing non-POD types in a union, so if you went this route, you'd have to use a char * as above, not an actual std::string.
One way to remove (most of) those limitations is to use an inheritance-based model:
class Data {
public:
virtual ~Data() { }
};
class StringData : public Data {
std::string content;
public:
StringData(std::string const &init) : content(init) {}
};
class IntData : public Data {
int content;
public:
IntData(std::string const &init) : content(init) {}
};
This is somewhat incomplete, but I think probably enough to give the general idea--you'd have an array (or vector) of pointers to the base class. To insert data, you'd create a StringData or IntData object (allocating it dynamically) and then store its address into the collection of Data *. When you need to get one back, you use dynamic_cast (among other things) to figure out which one it started as, and get back to that type safely. All somewhat ugly, but it does work.
Even with C++11, you can use a template-based solution. For example, Boost::variant, can do this job quite nicely. This will provide an overloaded constructor and value semantics, so you could do something like:
boost::variant<int, std::string> some_object("input string");
In other words, it's pretty what you'd get if you spent the time and effort necessary to finish the inheritance-based code outlined above--except that it's dramatically cleaner, since it gets rid of the requirement to store a pointer to the base class, use dynamic_cast to retrieve an object of the correct type, and so on. In short, it's the right solution to the problem (until/unless you can upgrade to a newer compiler, and use std::variant instead).
Apart from the problem in given code described in comments/replies.
I am trying to answer your question
vec.push_back(id, &myData<?>); //how can I set the template param to be the type myData point to?
Before that you need to modify vec definition as following
vector<dataStruct<void>> vec;
Now you can simple push element in vector
vec.push_back({id, &mydata, bb});
i have tried to modify your code so that it can work
#include<iostream>
#include<vector>
using namespace std;
template<typename T>
struct dataStruct
{
int id;
T** data;
bool mybool;
};
void readData(int &ID, void*& data, bool& mybool)
{
if (mybool)
{
data = new string("bla");
}
else
{
int b = 0;
data = &b;
}
}
int main ()
{
void* mydata = nullptr;
vector<dataStruct<void>> vec;
bool bb = false;
for (int id = 0; id < 5; id++)
{
if (id%2) bb = true;
readData(id, mydata, bb);
vec.push_back({id, &mydata, bb});
}
}

Initializing an array outside class after declaration

For example:
const int m = 10;
class C{
public:
double A[m];
};
int main(){
C name;
name.A[m] = ... // initializing here?
}
I can't find a way around that, I could for example do
C name = {...};
Which would perfectly work but for the sake of functionality I wanna know if I can do that for single variables inside the class.
In your example, you only need to write:
name.A[x]=value;
Where value is double and x is between 0 and 9. You can also make a loop if you wish to set values for all or some of its elements.

Having difficulty in creating a templatized generic vector which can hold any datatype

As the topic suggests, I am trying to create a vector of which can hold any datatype. I am trying to use templates so that code can be more maintainable for future.
#include<iostream>
#include<memory>
#include<vector>
struct prime{
public:
template<typename T>
T get();
};
template<typename T>
struct foo: prime{
public:
T i;
foo(T k):i(k){
}
template<typename T1>
T1 get(){
return i;
}
};
/*
struct fooString :prime{
public:
std::string i;
fooString(std::string k):i(k){
}
};
*/
int main(){
std::vector<std::shared_ptr<prime>> v;
std::shared_ptr<foo<int>> p1 = std::make_shared<foo<int>>(0);
std::shared_ptr<foo<char>> p3 = std::make_shared<foo<char>>('H');
//std::shared_ptr<fooString> p2 = std::make_shared<fooString>("HK");
v.push_back(p1);
v.push_back(p3);
//v.push_back(p2);
//std::cout<<v[0]->i<<" "<<v[1]->i<<std::endl;
//std::cout<<static_cast<foo<int>>(*v[0]).get();
std::cout<<v[0]->get<int>();
}
The commented code is my different approaches I am trying to solve this issue. But I am not able to crack this. Any suggestions would help me a lot. I tried following this SO but as I said, creating union of different datatypes is difficult to maintain. And also boost::variant doesn't help either as I have to give all the types it needs to hold before hand. I don't want that restriction. Can Anyone suggest me whether it is possible or I am just trying to achieve the impossible?
I have another algorithm in my mind which is like cast everything to string and store it. But that approach doesn't look proper.
Thank you :)
If what you want is to have a container that can store any type, but not actually give you any information about it - it's up to you to just know which type each element is actually storing, then that's precisely what std::any (based on Boost.Any) is for.
The usage in your case would be:
int main(){
std::vector<std::any> v;
v.push_back(0); // an int
v.push_back('H'); // a char
v.push_back(std::string{"HK"}); // a string
std::cout << std::any_cast<int>(v[0]); // this will throw if v[0] is not an int
std::string* p = std::any_cast<std::string>(&v[1]); // this will return nullptr
// if v[1] is not a string, which
// it is not
}

How to adress variable by name stored in another variable (C++)

Good day,
I would like to reference a structure in a function by using a variable to store its name. Is this possible to do something like this in C++?
Definitely, all existing structures will be declared and initialised before any call is made (probably as global) and I will build in a check to make sure that only existing structures are referenced.
I would like something in this spirit:
struct StructName
{
...stuff
}a,b,c;
StructName a;
StructName b;
.
.
.
etc. including setting required values (in initialisation or elsewhere in code as needed)
and then I would have something like this to call from another portion of code:
void myFunction(char someInput)
{
some stuff
some stuff
externalFunction(static parameter, static parameter, _someInput_, static parameter);
yet some other stuff
}
where somInput is either a,b or c.
Please bear in mind I am a beginner with C, with little to no formal training in subject matter.
Thank you.
edit: If it was just myself, I would make do with case switch for someInput, referencing the structure directly in each case, but this part of a code is meant to be extendable by a non-programmer who would supply structures themselves, I would provide to him a template of structure initialisation code, and he would add the initialisation code to a specified place in the code, ammend the list of allowed names and compile the library.
You cannot convert a char or a char const * (runtime data) into a type (compile time information).
[edit] Well, actually you can with something like the following code, but since it uses templates, it will still be available only at the compile time, so you will not be able to pass function parameters, for example.
template < char C >
struct GetType;
template < >
struct GetType< 'a' > {
typedef struct { int foo; } type; };
template < >
struct GetType< 'b' > {
typedef struct { int bar; } type; };
GetType< 'a' >::type foo;
GetType< 'b' >::type bar;
Variable names disappear as part of the compilation step(s) in C and C++.
Typically, there are two scenarios that solve the type of problem you are describing:
User input corresponds to specific variable name.
You don't actually want the "name" of the variable, but just need a way to associate different data with different parts of your code.
In the second, simpler case, just use an array, and use the index to the element you want as the way to associate the correct data.
In the first case, you can use a std::map<std::string, structname&>. A std::map acts sort of like an array, but it is indexed by the first type give in the template parameters to std::map - so in this case, you can use std::string as an index.
Something like this:
#include <map>
#include <iostream>
#include <string>
struct StructName
{
int x;
};
std::map<std::string, StructName *> vars;
StructName a;
StructName b;
void registerVars()
{
vars["a"] = &a;
vars["b"] = &b;
}
int main()
{
std::string v;
registerVars();
while(std::cin >> v)
{
std::cin.ignore(1000, '\n');
if (vars.find(v) == vars.end())
{
std::cout << "No such variable" << std::endl;
}
else
{
vars[v]->x++;
std::cout << "variable " << v << " is " << vars[v]->x << std::endl;
}
}
return 0;
}

How to return an array of structs from a class in a getter function

I have a relatively simple question but I cant seem to find an answer specific for my case and I just may not be approaching this problem the right way. I have a class that looks like this:
struct tileProperties
{
int x;
int y;
};
class LoadMap
{
private:
ALLEGRO_BITMAP *mapToLoad[10][10];
tileProperties *individualMapTile[100];
public:
//Get the struct of tile properties
tileProperties *getMapTiles();
};
I have an implementation that looks like this for the getter function:
tileProperties *LoadMap::getMapTiles()
{
return individualMapTile[0];
}
I have code in the LoadMap class that will assign 100 tile properties for each struct in the array. I want to be able to access this array of structs in my main.cpp file but I just cant seem to find the right syntax or approach. My main.cpp looks like this.
struct TestStruct
{
int x;
int y;
};
int main()
{
LoadMap _loadMap;
TestStruct *_testStruct[100];
//This assignment will not work, is there
//a better way?
_testStruct = _loadMap.getMapTiles();
return 0;
}
I realize that there are many approaches to this, but I'm trying to keep this implementation as private as possible. If someone could please point me in the right direction I would greatly appreciate it. Thank you!
TestStruct *_testStruct;
_testStruct = _loadMap.getMapTiles();
This will get you a pointer to the first element in the array returned. You can then iterate through the other 99.
I would highly recommend using vectors, or another container, and writing getters that don't return pointers to bare arrays like that.
First of all, here, why do we need TestStruct, you can use "tileProperties" structure itself...
And imp thing,
tileProperties *individualMapTile[100]; is array of pointers to the structure.
Hence, individualMapTile will have pointers in it.
You have returned the first pointer, hence you can access the first structure only. What about the others????
tileProperties** LoadMap::getMapTiles()
{
return individualMapTile;
}
int main()
{
LoadMap _loadMap;
tileProperties **_tileProperties;
_tileProperties = _loadMap.getMapTiles();
for (int i=0; i<100;i++)
{
printf("\n%d", (**_tileProperties).x);
_tileProperties;
}
return 0;
}
Use vectors instead of arrays where possible. Also consider an array/vector of TestStruct directly rather than pointers to them. I can't tell if that would be appropriate for you from your code sample.
class LoadMap
{
public:
typedef vector<tileProperties *> MapTileContainer;
LoadMap()
: individualMapTile(100) // size 100
{
// populate vector..
}
//Get the struct of tile properties
const MapTileContainer& getMapTiles() const
{
return individualMapTile;
}
MapTileContainer& getMapTiles()
{
return individualMapTile;
}
private:
MapTileContainer individualMapTile;
};
int main()
{
LoadMap _loadMap;
LoadMap::MapTileContainer& _testStruct = _loadMap.getMapTiles();
}