C++ data structure where initialization can use its names - c++

I need to create a data structure that has a LOT of members. Example:
struct MyStruct {
int varSomething;
int helloNumber;
int thisIsSomething;
...
int varNumber50;//50th element
}
The problem with this struct is that when I want to instantiate it, I need to do the following:
my_vector[i] = MyStruct{10, 4, 90, ...}
as you can see, I need to put lots of values and I end up confusing which one is which. Ideally, I'd like to do something like this:
my_vector[i] = MyStruct{varSomething = 10, helloNumber = 4, thisIsSomething = 90, ...}
Since each variable has a name, I know what I'm doing, and can't confuse.
I know that I can do this:
MyStruct myStruct;
MyStruct.varSomething = 10;
myStruct.helloNumber = 4;
...
my_vector[i] = myStruct
but I want to create an anonymous struct, it's not nice to create a named struct just to put in the vector.
What should be a great way to solve this problem? Is there something similar to a struct that can achieve what I want??

With c++20 designated initializers you can do the following
struct MyStruct {
int a,b,c;
};
int main(){
MyStruct my_value {
a : 2,
b : 3,
c : 95
};
}
In this case I would recommend against using this as it is a definite code smell.
You need to rethink your design and maybe looking at design patterns like factory, builder or prototype to give you a better idea on how to create your objects.
See the following links for more information:
https://en.cppreference.com/w/cpp/language/aggregate_initialization#Designated_initializers
https://en.wikipedia.org/wiki/Creational_pattern

Related

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

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;
}

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
};

SWIG how to access a byte array from a c struct in Lua using a Lua table to manipulate

I am trying to access a array in a c struct from Lua. I want to access it as byte array. I know I have to use
typemaps somehow but I am not able to get it working like I want to.
the struct is defined within a namespace if that matter at all. For this example
I call the headerfile send.h
namespace foo{
namespace bar{
typedef struct
{
...
unsigned char data[8];
} message;
}};
So I want to be able to access the unsigned char data array from the c struct from Lua.
I want to access it like a table with numbers. Here my Lua script code I want to
use.
modul = require("MyModule")
msg = modul.message()
msg.data[1] = 0x3b
print(msg.data[1])
All what I get is an error like "attempt to index field 'data' (a userdata value)"
I did some research and found out that I have to add some kind of %typemap magic to
deal with that. But I was not able to figure out exactly how.
So here my questions:
Can someone point me to a working example of that scenario?
What kind of typemap should I apply?
How can I apply such a typemap only to this struct and not to others?
So, finally I figured out that simple by using below typemap I'm able to access the data member just the way I want to. Hope that will help someone else.
%typemap(out) unsigned char foo::bar::message::data[8]
{
int i;
int32_t _size = 8;
lua_newtable(L);
for (i = 0; i < _size; i++)
{
lua_pushnumber(L, (lua_Number)$1[i]);
lua_rawseti(L, -2, i + 1);
}
SWIG_arg++;
}
%include "send.h"
%{
#include "send.h"
%}

Is there a convenient way to initialize simple structs in C++?

Let's say I have a simple struct like this:
struct Simple
{
int weight;
std::string name;
float power;
};
I'd like to be able to initialize one of these without creating a constructor for it and without having to individually set its parameters. I dream of a syntax like this, for example:
Simple s( 4, "bill", 3.1f );
...or perhaps...
Simple s = { 4, "bill", 3.1f };
...or verily...
Simple s{ 4, "bill", 3.1f };
I know that I can get the first example to work by adding a braindead constructor of my own. Tedious.
Likewise, the last example will work in C++11, but I believe I have to provide the constructor.
Is there a way to simply and elegantly initialize a struct in C++ without having to provide a constructor?
Simple s = { 4, "bill", 3.1f };
Simple s{ 4, "bill", 3.1f };
These are valid.
This syntax will map each value in the above groups/sets to each struct member variable depending on the order and you don't even need to define a constructor.

Using enum inside types - Compiler warning C4482 C++

I am using fully qualified name of the enum inside a method in one of my class. But I am getting compiler warning which says "warning C4482: nonstandard extension used: enum 'Foo' used in qualified name". In C++, do we need to use enums without the qualified name? But IMO, that looks ugly.
Any thoughts?
Yes, enums don't create a new "namespace", the values in the enum are directly available in the surrounding scope. So you get:
enum sample {
SAMPLE_ONE = 1,
SAMPLE_TWO = 2
};
int main() {
std::cout << "one = " << SAMPLE_ONE << std::endl;
return 0;
}
To make it clean, replace:
enum Fruit {
ORANGE = 0,
BANANA = 1
};
with
namespace Fruit {
enum { //no enum name needed
ORANGE = 0,
BANANA = 1
};
};
...
int f = Fruit::BANANA; //No warning
While sth does answer the question, it didn't address how I've always used enums. Even though they're just more or less names for numbers, I've always used them to define types that can only have certain values.
If the enum is part of the class, then that helps consumers clearly identify an enum reference:
class Apple {
enum Variety {
Gala,
GoldenDelicious,
GrannySmith,
Fuji
}
...
};
Then consumers would be able declare instances of the enum, pass as parameters, and qualify them when referencing one of the types.
unsigned int GetCountOfApples( Apple::Variety appleVariety );
...
fujiCnt = GetCountOfApples( Apple::Fuji );
Sometimes you want an enum outside of a class or two enums in the same class, and you can do something like what Poy had. You won't be able to reference the enum type though, so just name it.
namespace Color {
enum ColorEnum {
Blue,
Red,
Black
};
Now using the enum and values would work like:
Color::ColorEnum firstColor = Color::Blue;
Color::ColorEnum secondColor = Color::Red;
if( firstColor == secondColor )
....
Now if there happens to be different enums with the same name in them, they will always be qualified with what type they are. Then you could handle what gamblor is asking about.
BananaColorEnum banCol = BananaColor::Yellow;
TomatoColorEnum tomCol = TomatoColor::Yellow;
Yes. Conceptually enum defines a type, and the possible values of that type. Even though it seems natural, to define enum foo { bar, baz }; and then refer to foo::baz is the same as referring to int::1.
namespace Company
{
typedef int Value;
enum
{
Microsoft= 0,
APPLE = 1,
};
};
namespace Fruit
{
typedef int Value;
enum
{
ORANGE = 0,
BANANA = 1,
APPLE = 2,
};
};
...
Fruit::Value f = Fruit::BANANA; //No warning
Company::Value f = Company::APPLE; //is different value then Fruit::APPLE
This works on GCC and MS compiler and Mac. And the advantage is that you can use namespace operator and pass conflicts. The little disadvantage is that instead of Fruit, you have to write Fruit::Value. it is more useful in large project when you don't know what enums are in other class.
If it is possible to use C++11 instead, it is much more simple, because the enum::namespace syntax is then possible.
The cleanest way I've found to do this is defining the enum as such
namespace Samples
{
enum Value
{
Sample1,
Sample2,
Sample3
};
}
typedef Samples::Value Sample;
Then in function and variable definitions you can use the typedef:
void Function(Sample eSample);
Sample m_eSample;
And in your .cpp file you can use the namespace to assign variables:
void Function(Sample eSample)
{
m_eSample = Samples::Sample1;
eSample = Samples::Sample2;
}
Personally, I think this is a compiler bug. I've been using C++ for lots of time. Sadly, no sample code in OP. The interpretation of an enum by the Java people was actually correct iMO. Mine, was like this ...
class Foo {
enum tMyEnum { eFirstVal = 0, eSecondVal = 1};
// ...
tMyEnum m_myVal;
};
void Foo::MyMethod() {
if(m_myVal == tMyEnum::eFirstVal) {
// ...
}
}
I also tried, Foo::tMyEnum::eFirstVal. Without the qualifiers, everything compiled.
I had the same problem and I'm not using C++ 11 yet. I much prefer fully qualified namespaces myself too.
I disabled this particular warning. I'm sure people will dislike the idea but some may be thankful..
#pragma warning( disable : 4482 )