struct with enum compilation error based on position - c++

This:
enum Id {
START,
INDENT
};
struct State {
int line;
int column;
Id id;
};
...
lexer::State state = {0};
compiles.
But if I put Id id as the first element of the struct, it stops. Can someone explain to me briefly why these two structs are treated differently.

You get an error because constant zero of type int is not compatible with the initial field id of type Id, unless
1) You add a cast, like this
lexer::State state = {static_cast<Id>(0)};
2) or use START in place of zero, like this
lexer::State state = {START};
3) or drop zero to value-initialize the whole struct (recommended):
lexer::State state = {};

Related

Create an instance of an object C++

I have recently picked up C++ but I am having problems in some areas as I am used to Java and I am not sure if I am going about things the right way.
I have a text file which lines are structured like this
C;101;1;1;4;10;
H;102;9;0;1;8;2
C;103;9;9;2;5;
C;104;0;9;3;8;
; being the delimeter
C is used to check if its a Crawler(H is used to check if it is a Hopper), it is then followed by the id, positions, directions(1-4), size, and alive(0/1)
I have an abstract Bug class then I have a Crawler and Hopper class which both inherit from the Bug class.
Here is my Bug class
class Bug
{
public:
int id;
pair<int, int> position;
int direction;
int size;
bool alive;
list<pair<int, int>> path;
virtual void move() {}
bool isWayBlocked() {}
Bug(string type, int id, pair <int, int> position, int direction, int size, bool alive)
{
type = type;
id = id;
position = position;
direction = direction;
size = size;
alive = alive;
};
};
Here is the Crawler class
class Crawler : public Bug
{
public:
Crawler(int id, pair <int, int> position, int direction, int size)
: Bug("Crawler", id, position, direction, size, alive)
{
}
};
Here is an example of me trying to create an instance of a Crawler object:
Bug* bugPtr;
if (bugType == "C") {
bugPtr = new Crawler(bugID, { xPos,yPos }, direction, size);
//Crawler* CrawlerBugPointer = new Crawler(bugID, { xPos,yPos }, direction, size);
}
I am able to easily read from the text file and store the variables but when i start debugging all of the fields in the bugPtr say 0, I suspect that I have gone about things in completely the wrong way and have not built the Abstract class and Inheritor classes properly, could anyone point out what I am doing wrong? any help will be much appreciated.
The compiler should have generated a warning, "Expression with possibly no effect" (or similar), for every line in your constructor. Read the warnings - they're useful.
Bug(string type, int id, pair <int, int> position, int direction, int size, bool alive)
{
this->type = type;
this->id = id;
this->position = position;
this->direction = direction;
this->size = size;
this->alive = alive;
};
While C++ doesn't require the ridiculous use of this everywhere, in your case it's necessary since you've given the constructor parameters the same names as the fields. When you enter something like
id = id;
You're saying, "Find the variable with name id in this scope, and assign its value to itself." Which does nothing, which is why all of your fields were left at their default values. Saying this.id means, "Find the class field with name id and assign the value of the local id to it."
The way to do this is with an initializer list:
Bug(string type, int id, pair <int, int> position, int direction, int size, bool alive)
: type(type), id(id), position(position), direction(direction), size(size), alive(alive)
{ }
The problem with the original code is name hiding. In the constructor body, type = type simply assigns the value of the argument named type to the argument named type. It doesn’t change the value of the member named type.
But in an initializer list, in an entry like type(type), the first type is the name of the member and the second type is the name of the argument. So the member gets the argument value, and all is well.
You should always use initializer lists in constructors. In addition to allowing duplicate names (if that’s what you like; many programmers don’t) they are more efficient when you have data members with more complex initialization.

How to set the default value of enum type variable?

How to set the default value of the enum type tip, I tried setting it to 0 or 1, or nothing, but I get the same error?
enum tip {
pop,
rap,
rock
};
class Pesna{
private:
char *ime;
int vremetraenje;
tip tip1;
public:
//constructor
Pesna(char *i = "NULL", int min = 0, tip t){
ime = new char[strlen(i) + 1];
strcpy(ime, i);
vremetraenje = min;
tip1 = t;
}
};
You must set it to one of the enum values, like:
Pesna(char *i = "NULL", int min = 0, tip t = pop)
// ^^^^^
Another techique is to use a Default value declared in the enum itself and use that one. This makes it easier if you change your mind later what the default should be:
enum tip {
pop,
rap,
rock,
Default = rap, // Take care not to use default, that's a keyword
};
Pesna(char *i = "NULL", int min = 0, tip t = Default)
// ^^^^^^^^^
Don’t think of enums as numbers like 0 or 1 (in some cases they can even be signed or unsigned). Think of them like more like a class/struct in the way that you refer to them. So using
tip = 1
wouldn’t make since because ‘tip’ isn’t a number, it’s its own entity. Without explicitly stating enums start somewhere else like
enum tip { pop = 7, ...}
the first enum will start at 0. So you can cast/uncast using those representations with ‘numbers’, but again I would be careful with that. Also in general, it’s nicer to declare class-specific enums inside the class’s public namespace like
class Pesna {
public:
enum tip { pop, ...}
and then use the scope resolution operator to access them
Pesna::tip

c++ using structs as data for a <map, <map, vector>>

I am having a problem trying to load a map that has another map/vector combination as the value with structs. Below is my code which I have tried to simplify as much as I could:
//These are the structs
struct Order
{
std::string A;
std::string B;
};
struct Card
{
std::string C;
std::string D;
};
struct Item
{
std::string E;
std::string F;
};
//this is the method that will read and load the map
void LoadMap(ListofValues object)
{
std::map<Order, std::map<Item, std::vector<Card>>> records; //THIS is the data structure I'm trying to store into
//ListofValues is a list passed that holds all these values that will need to be put into my map
for(std::vector<ListofValues>::iterator vIter= object.begin(); vIter != object.end(); ++vIter)
{
std::string sReceiptRecord = (*vIter).getReceipt(m_StdOrderConfirmVer);
Order order = {(*vIter).getA,(*vIter).getB};
Item item = {(*vIter).getC,(*vIter).getD};
Card card = {wws::String((*vIter).getE), (*vIter).getF};
records[order][item].push_back(card); //load into my map
}
}
So I will have an object passed that contains a list of all the values (ListofValues). I will iterate through that list and with the getter methods, I will store those values into the structs (getE returns a Long which is why the conversion was necessary). Is there a step I'm missing
An error I'm getting is:
error C2678: binary '<' : no operator found which takes a left-hand operand of type 'const Order' (or there is no acceptable conversion)
You need to provide an operator < for your struct to be used as a key for the map, see this question: Struct as a key in a std::map
ListOfValues is the TYPE of the parameter passed to LoadMap, object is the actual variable.
In your for loop, you need to say object.begin() and object.end().
I'm getting very different compiler errors than what you say you're getting. Did you post the right code?
Here's what I see: https://godbolt.org/g/xl4zWw

How to Access a Struct Inside a Struct in C++?

I'm trying to access the variables string ModelName and int Sales like this Dealer.Modelo.ModelName but it's not working. How can I access those variables to fill the the structure?
PD: The compiler says that "Dealer" should have a class type.
const int MAXIMODEALERS = 20;
const int MAXIMOMODELOS = 6;
struct Detail
{
string ModelName;
int Sales;
};
struct Element
{
string CompanyName;
Detail Modelo[MAXIMOMODELOS];
};
Element Dealer[MAXIMODEALERS];
Element Dealer[MAXIMODEALERS];
declares an array of objects of type Element, but :
Dealer.Modelo.ModelName = "something";
is treating Dealer as it would be a single instance of Element, neither an array. You need to use an index to access concrete element (same for the Modelo):
Dealer[SomeIndex].Modelo[OtherIndex].ModelName = "something";

Conception of a class with some attributes that will not be logically defined

I have the following class :
class Foo
{
public:
...
private:
int a;
int b;
int c;
int d;
int e;
int f;
}
The program will affect a value to some of those variables and others should not be in a valid state for the logic of my program. What is a good way of handling those variables who should not have values? Should I give them a random value (ex 68823773)? This doesn't seem like a clean solution to me.
If you don't have a "singular" value (e.g., 0 or -1) to indicate a special value, you could use boost::optional
If you want to avoid using boost library then you may use std::pair instead of int. Then you may set the bool flag appropriately to determine a valid state.
For example:
std::pair<int, bool> value;
afterwards when the value has a valid state you may set the flag as below:
value.first = <some_value>;
value.second = true;
similarly you may reset rest of the members in the class. To check whether the value is in valid state you may use
if (value.second)
{
// true means valid state
// Do your processing here
}
And lastly you may use an array or std::vector of std::pair instead of a series of variables. This way, for some particular condition, you can set the flag for certain index and reset (set false) the flag for all the other index.