C++ Assign std::map values with enum class object - c++

Consider following code.
In my real case scenario i have somthing like that:
typedef enum
{
vehicle,
computer,
} Article;
And that is what I'm trying to construct:
enum class status{
notPaid,
paid,
};
struct S {
status status_vehicle;
status status_computer;
std::map<Article, status> mymap =
{
{vehicle, S::status_vehicle},
{computer, S::status_computer},
};
};
int main ()
{
Article a1 = vehicle;
S::mymap.at(a1) = status::paid; // this line doesn't work
}
However, the last line (S::mymap.at(a1) = status::paid;) is not working. I've tried different approaches, using the find() function of std::map for example. I got the error "assignment of member std::pair<Article, status>::second in read only object".
Does someone know, how to do that? Also maybe how to design the whole in a better way? (the whole from the line "And that is what I'm trying to construct").
Also I would have prefer to use an unordered_map instead of a map but was not working. Thanks

Because mymap is not static.
You can do like this:
Article a1 = vehicle;
struct S mystruct;
mystruct.mymap.at(a1) = status::paid;
Or add static to your member in struct:
struct S {
status status_vehicle;
status status_computer;
static std::map<Article, status> mymap;
};
But when using static, you have to initialize mymap outside declaration of struct S and member that you can't use non-static members of struct
std::map<Article,status> S::mymap={
{vehicle,S::status_vehicle}
};
A static member is shared by all objects of the class. All static data
is initialized to zero when the first object is created, if no other
initialization is present
And logically is not good in your example
https://en.cppreference.com/w/cpp/language/static

Since myMap is non-static, it cannot be assigned as static variables are.
You can change your code like this:
int main ()
{
Article a1 = vehicle;
S ss;
ss.mymap.at(a1) = status::paid;
}

Related

Unable to create class vector of structs

I am trying to create an empty vector of structs. I will be adding elements at runtime with push_back().
The overall structure is a separate class has a vector of Resource objects, and each Resource object is supposed to have this struct vector, pipeline. I don't understand why this declaration is not being treated as a regular class variable. In Resource.cpp, the hint vscode gives me mentions something about an allocator. I neither know what that is, nor know how it applies.
Resource.h
#include <vector>
class Resource {
public:
int typeSize;
typedef struct PipelineSlot{
bool isBusy;
uint32_t busyCycle;
Instruction *occupiedBy;
} pls_t;
std::vector<pls_t> pipeline; //why doesn't this create a class variable?
static bool pushFU(Instruction* instr, int cycle, std::vector<Resource> &fuVector);
};
Resource.cpp
#include <Resource.h>
typedef struct PipelineSlot pls_t;
static bool pushFU(Instruction* instr, int cycle, std::vector<Resource> &fuVector) {
for (auto fu : fuVector) {
std::vector<pls_t> pipe = fu.pipeline; //IDE doesn't like this
if (fu.pipeline.size() > 0) {
if (fu.pipeline.back().busyCycle != cycle && fu.pipeline.size() < Resource::resourceLatency.find(fu.type)->second) {
pls_t newInstr {true, cycle, instr};
fu.pipeline.push_back(newInstr); //IDE doesn't like this
return true;
}
} else if (fu.pipeline.size() == 0) {
pls_t newInstr {true, cycle, instr};
fu.pipeline.push_back(newInstr); //IDE doesn't like this
return true;
}
}
return false;
}
Not sure if it's relevant, but IDE only has an issue with the push_back() calls, not with the other vector methods (which I also don't understand). The end goal is to have a class vector of structs that I can modify at run time. How do I achieve this?
EDIT: VSCode gives me this hint when I hover over the push_back() lines:
no instance of overloaded function "std::vector<_Tp, _Alloc>push_back [with _Tp=Resource::pls_t, Alloc=std::allocator<Resource::pls_t]" matches the argument list -- argument types are: (pls_t) -- object type is: std::vector<Resource::pls_t, std::allocator<Resource::pls_t>>
Compiler tells me this (lots of these errors):
error: ‘class Resource’ has no member named ‘pipeline’; did you mean ‘typeSize’?
if (fu.pipeline.size() > 0) { behavior
Note: I am a college student with a background in c, but am VERY new with c++.
So here's the fundamental error
class Resource
{
typedef struct PipelineSlot {
bool isBusy;
uint32_t busyCycle;
Instruction *occupiedBy;
} pls_t;
};
Because PipelineSlot is inside the Resource class the names created here are Resource::PipelineSlot and Resource::pls_t, not (as you seem to think) PipelineSlot and pls_t.
Outside of the Resource class PipelineSlot and pls_t must be qualified with Resource::. So this code would work
std::vector<Resource::pls_t> pipe = fu.pipeline;
So would moving the struct outside of the Resource class. That's probably what you should do.
But then you've confused things even further by creating a new typedef typedef struct PipelineSlot pls_t;. This is a completely different definition from the previous one, because it is given outside the Resource class, and the types declared here PipelineSlot and pls_t have no relation at all to the previously declared types.
Use:
std::vector<Resource::pls_t> pipe = fu.pipeline;

Access struct enum from object

I am just learning to use c++ and I'm trying to understand how scope works with classes and embedded enums.
Currently I have a class which looks something like this:
class Foo {
public:
Foo();
enum Option = {
FIRST,
SECOND,
THIRD
};
struct Example = {
const char* name;
Option key;
enum keyOption = {
PROPERTY,
FLAG
} keyValue;
};
};
Then in my main function I initialize it and then add some values to the Example struct
int main()
{
Foo *test;
Foo::Example content = {
"Hello World",
test->FIRST,
test->Example::PROPERTY
};
}
With the above code I will get an error of:
error: 'Foo::keyOption' is not a base of 'Foo'
I know I can fix it by changing test->Example::PROPERTY to Foo::Example::PROPERTY
But is there a way I can access the Example structs values through the object instead of Foo::? Similarly to how I access the FIRST value?
Forgive me if I'm butchering the naming of difference concepts, I'm just trying to teach myself by building something, and I will need to read more into the details soon.
Thank you so much for any help, it is really appreciated!
Foo::FIRST and Foo::Example::PROPERTY are possible values of the enumerator. Only Example::key and Example::keyValue are members of the struct which can be instantiated and initialized to Foo::FIRST and Foo::Example::PROPERTY
This should work
Foo::Example content = {
"Hello World",
test->FIRST,
Foo::Example::PROPERTY
};

Sharing static data members between different classes that can create instances of eachother

I have written a class (AbcdBase) which holds several static objects, these include maps and a few static objects that act as "helper tools" such as plotting helper functions, objects which store constants for making tables and so on.
Separately I have other classes (DataSample and DoABCD) that need access to those static members, the twist is that DoABCD creates several instances of DataSample. What would be the correct way of coding this? Having both DataSample and DoABCD be derived classes of AbcdBase doesn't seem like the correct way (and I get Seg violations when I do that).
class AbcdBase {
private:
int init();
int status;
public:
static SampleAggregator* SampleAggregatorInst;
static PlotHelper* PlotHelperInst;
static DataSampleConst* DataSetMap;
static DataSampleConst::SampleDict* ListOfSamples;
static std::vector<std::string> ListOfPlots;
static std::vector<std::string> ListOfRegions;
static Logger* LoggerInst;
AbcdBase();
virtual ~AbcdBase();
typedef enum {
A = 1, B = 2, C = 3, D = 4
} RegionEnum;
typedef enum {
MET = 1, ETCONE20 = 2
} DimensionEnum;
ClassDef(AbcdBase, 1)
};
Is a singleton the correct way of solving this issue? so that whenever DataSample or DoABCD need access to a member of AbcdBase they instance() function gets called which returns a pointer to a private instance of AbcdBase. I feel like this would clutter the code a LOT.
Thanks
Separately I have other classes (DataSample and DoABCD) that need access to those static members
Merely declare those static member public, as you have done, and then reference them in any other code (including the code in DataSample or DoABCD:
class DataSample {
...
int GetFragle(void) {
return AbcdBase::PlotHelperInst->m_fragle;
}
...
};
No need to do anything.
They're already public, you can use AbcdBase::PlotHelperInst from ANYWHERE.

struct object declaration

hello every i have made a structure and i want to make 2 objects of it . i am using qtcreator.
i write
struct grapharray gao ; (grapharray is my structure)
every thig works well but when i write another object like
struct grapharray gao ;
struct grapharray gao1 ;
my program unexpectedly finishes can any one tell me why is it so and where should i declare the struct object
struct grapharray
{
int structcol;
double *structpayloadgraph;
double *structsessiongraph;
};
here is my structure;
and i have a function
struct grapharray graphplotdata(char * filename)
{ // computing some values and returning structure object
}
thanks
If I understand well the problem, I would say that you use far too much the "struct" keyword.
If you define your struct as
struct grapharray
{
int structcol;
double *structpayloadgraph;
double *structsessiongraph;
};
then you don't need to use the keyword "struct" when declaring the variables.
grapharray gao; // without struct keyword
grapharray gao1; // without struct keyword
and your function should be
grapharray graphplotdata(char * filename) // without struct once again.
{
// computing some values and returning structure object
}
structs does works almost the same way as classes; the main difference is that structs members and methods are "public" by default and classes members and methods are "private" by default.
Edit: Considering the comment of Dennis Zickefoose, this is not the good answer.

Populate a static member container in c++

I've got a static class member which is some container, like
(Foo.h)
class Foo
{
...
private:
static list<string> s_List;
}
I need to populate the list with a number of specific values. Actually it should be also const, but that might overcomplicate the problem further.
All the class member functions are static, so initializing it in a constructor doesn't make sense.
a common solution is to do something like this:
// header
class Foo
{
...
private:
static list<string> s_List;
}
// cpp
list<string> init()
{
list<string> tmp;
... fill tmp with strings
return tmp;
}
list<string> Foo::s_List(init());
the other method is like Neil Butterworth suggested.
Another alternative is to create a simple initialiser class:
list <string> Foo::s_List;
struct Init {
Init() {
Foo::s_List.insert("apple");
Foo::s_List.insert("bannana");
Foo::s_List.insert("grapes");
}
};
static Init doInit;
Note that, as the list is private, this will probably require you to make Init a friend of Foo. It's also often convenient to make such classes be contained by the class they are initialising.
However, I just re-read your question and another thought occurs - if the list is const, you will presumably not be changing it, in which case a simple array of strings, initialised with the strings in sorted order may be a better solution. It will certainly be faster to search (using std::binary_search) than a list, and can of course be easily initialised.
If your compiler supports C++0x, this is actually trivial to accomplish.
#include <iostream>
#include <list>
class Foo
{
public:
static std::list<std::string> s_List;
};
std::list<std::string> Foo::s_List = {"hello", "world", "asdf", "qwerty"};
int main()
{
for(const std::string& str : Foo::s_List)
std::cout << str << std::endl;
return 0;
}
This works for both const and non-const static members. I've tested this snippet with clang-4.2, gcc-4.7, gcc-4.6, and gcc-4.5. Gcc-4.5 does not support the updated for syntax, so you'd have to use a traditional for loop with iterators. Also, don't forget to pass the -std=c++0x flag to the compiler. I'm reasonably confident Visual Studio supports this as well, but I don't know for sure and don't know which versions.
It depends on what values you need to put in that list. Are they static or do they require some form of computation?
If they are static, you can do this:
namespace {
const char* const initVals[] = { "A", "B", "C" };
}
list<string> Foo::s_list(initVals, initVals + 3);
one possible solution would be to use an accessor method that checks to see if it is initialized, and does so if it isn't.
The ways I(the author of the question) have vainly tried to do this.
I tried to do smth like (in Foo.cpp):
list<string> Foo::s_List = list<string>();
Foo::s_List.insert("apple");
Foo::s_List.insert("bannana");
Foo::s_List.insert("grapes");
But that gives a compiler error.
Then I thought of making an Initialize() method and calling it right from the code
void Foo::Initialize()
{
s_List.insert("rats");
s_List.insert("cats");
}
Foo::Initialize();
// error: compiler considers it to be a redefenition of the method, not a call.
The only viable idea left (havent yet tried) would be to check if the list is empty in each method that uses it, and if it's the case, call Initialize(). But that's ugly!