Initialising C structures in C++ code - c++

Is there a better way to initialise C structures in C++ code?
I can use initialiser lists at the variable declaration point; however, this isn't that useful if all arguments are not known at compile time, or if I'm not declaring a local/global instance, eg:
Legacy C code which declares the struct, and also has API's using it
typedef struct
{
int x, y, z;
} MyStruct;
C++ code using the C library
void doSomething(std::vector<MyStruct> &items)
{
items.push_back(MyStruct(5,rand()%100,items.size()));//doesn't work because there is no such constructor
items.push_back({5,rand()%100,items.size()});//not allowed either
//works, but much more to write...
MyStruct v;
v.x = 5;
v.y = rand()%100;
v.z = items.size();
items.push_back(v);
}
Creating local instances and then setting each member one at a time (myStruct.x = 5; etc) is a real pain, and somewhat hard to read when trying to add say 20 different items to the container...

If you can't add a constructor (which is the best solution in C++03 but you probably have compatibility constraint with C), you can write a function with the same effect:
MyStruct makeAMyStruct(int x, int y, int z)
{
MyStruct result = { x, y, z };
return result;
}
items.push_back(makeAMyStruct(5,rand()%100,items.size()));
Edit: I'd have checked now that C++0X offers something for this precise problem:
items.push_back(MyStruct{5,rand()%100,items.size()});
which is available in g++ 4.4.

You're looking for C99 compound literals. Example code:
struct foo *foo = malloc(sizeof *foo);
*foo = (struct foo){ bar, baz };

How about:
MyStruct v = {5, rand()%100, items.size()};
items.push_back(v);

Create a function to initialize it, similar to what a C++ constructor would do.

Not clear what you are asking. In C++, the obvious solution is to give the struct a constructor:
struct MyStruct {
int x, y, z;
MyStruct( int ax, int ay, int az ) : x( ax ), y( ay ), z( az ) {}
};

Another option is to derive from the struct and add a constructor there.
struct MyDerivedStruct : public MyStruct
{
MyDerivedStruct(int xi, int yi, int zi)
{
x = xi;
y = yi;
z = zi;
}
}
Then you can use this derived type in your own code and pass it to the C library when necessary. The language should take care of implicitly converting to MyStruct when appropriate.
As a bonus, you could also add other useful member functions, perhaps even wrapping many of the legacy C functions that use this type.

Related

C++ Unintialized struct member - field does not exist

I have the below structures in my C++ code.
struct XYZ {
double x;
double y;
double z;
};
struct Data {
XYZ xyz_point;
double item_1;
double item_2;
double item_3;
};
In my code I create a vector of structure Data.
std::vector<Data> data_vector;
for (i = 0; i < 5; i++) {
Data data_point_1;
data_point_1.xyz_point.x = 10.0;
data_point_1.xyz_point.y = 11.0;
data_point_1.xyz_point.z = 12.0;
data_point_1.item_1 = 13.0;
data_point_1.item_2 = 14.0;
data_point_1.item_3 = 15.0;
data_vector.push_back(data_point_1);
}
Code build successful without any errors, however during the CPP_Check I get the below warnings/error. data_point_1 does not have the field x, y and z.
[test.cc:122]: (error: uninitStructMember) Uninitialized struct member: data_point_1.x
[test.cc:122]: (error: uninitStructMember) Uninitialized struct member: data_point_1.y
[test.cc:122]: (error: uninitStructMember) Uninitialized struct member: data_point_1.z
Could you please help me to resolve this.
Thank you,
push_back requires a default constructor. The compiler is able to supply that, but it doesn't initialise the doubles.
CPP_Check is spotting that.
One fix is to use emplace_back instead with the initialiser-list syntax. That doesn't require a default constructor. Another option is to supply a default constructor that initialises the members.

Structure constructor in other structure

I am trying to create Voronoi diagram for some given points. Each points have different attributes and I want to denote it as color. To map my own Point structure with Boost Point concept, I have written some code. I have the following setup:
struct Point {
double a;
double b;
Point(double x, double y) : a(x), b(y) {}
};
// This Point structure is mapped to Boost Point concept. Code emitted
I have another structure as :
struct Point_Collection {
Point xy(double x, double y);
short color;
};
Visual Studio created an automatic definition as :
Point Point_Collection::xy(double x, double y)
{
return Point();
}
Now if I try to instantiate an object of Point_collection as:
std::vector<Point_Collection> *test;
test = new std::vector<Point_Collection>();
Point_Collection xy_color;
for (int i = 0; i < 5000; i++) {
xy_color.xy(rand() % 1000, rand() % 1000);
xy_color.color = rand() % 17;
test->push_back(xy_color);
}
I get an error.
error C2512: 'Point': no appropriate default constructor available
Can someone point me in the right direction why is this happening?
Point xy(double x, double y); declares a member function in Point_Collection that is identified by xy, accepts two doubles and returns a Point object by value.
If you want a simple aggregate that holds a point, the C++11 and onward way would be to define it like this:
struct Point_Collection {
Point xy;
short color;
};
Point_Collection xy_color{ { rand()%100, rand()%100 }, static_cast<short>(rand()%16)};
The above is a simple aggregate initialization using value initialization syntax. You should prefer it for two reasons:
It will not allow narrowing conversions. (Which int to short is, therefore the cast).
It's easy to implement. It requires no typing if your class has all public members.
(Also rand has better alternatives in C++11, check out the header <random>)
If you don't have access to C++11, then you can either write a constructor for Point_Collection.
struct Point_Collection {
Point xy;
short color;
Point_Collection(Point xy, short color)
: xy(xy), color(color) {}
};
Point_Collection xy_color (Point(...,...), ...);
Or use aggregate initialization with more verbose syntax:
struct Point_Collection {
Point xy;
short color;
};
Point_Collection xy_color = { Point(rand()%100, rand()%100), rand()%16 };
(Since the above is C++03, rand()%16 will be silently converted to short, despite it being narrowing).

How to call a function-like class (a class whose constructor does all the work)

I'm asking this just to know - not necessarily my code will end up using this strategy.
Suppose I have a class similar to this:
class Calc
{
public:
Calc( int &X, int &Y, CalcType aType )
{
int h = Helper( X );
// All the hard work will be done here.
}
int Helper( int I ) { // Do something }
enum CalcType
{
Add,
Sub,
Mul,
Div
};
};
Will optimisation remove this call:
Calc( X, Y, Calc::Add );
Will it remove this:
Calc iCalc( X, Y, Calc::Add ); // iCalc will be unused hence after.
Any reasons not to do something like this (where the work is done in the constructor)?
Answer is no, just because object isn't used doesn't mean the instantiation will be optimized out.
If the constructor is empty and the object is never used or only created as a temporary, it is possible for a smart compiler to optimize it away. In your case since " // All the hard work will be done here. " this is not the case.

What is the best way to indicate that a double value has not been initialized?

I have a class CS which is to represent the co-ordinate system in 3D i.e.(x, y, z)
class CS
{
private:
double x;
double y;
double z;
}
CS::CS()
{
x = NULL;//this causes x = 0//i want the address of x to be 0x000000 & not x = 0
y = NULL;
z = NULL:
}
I want that the user can create a CS (0, 0, 0).
In the constructor i want to initialise the address of x, y & z to NULL.
this is to differentiate between the user defined (0, 0, 0) & the default value.
I am creating the objects of CS dynamically, so there is no point in using the following code:
class CS
{
private:
double *x;
double *y;
double *z;
}
CS:CS()
{
x = new double;
x = NULL;
//same for y & z
}
Primarily, i want to manually assign 0x000000 address to any variable(int or double or char) without using pointers.
any suggestions?
You can't change the positions of x,y,and z to be NULL, since there positions will always be offsets from the CS object. They will always exist. It's not that CS has an x like you have a car, it's like CS has an x like you have a head. You can't not have a head. If they were integers, you would have to make them pointers (like you said you didn't want to do), because that would be the only way to tell uninitialized from initialized. However, doubles have a magic value that is rarely used:
CS:CS()
: x(std::numeric_limits<double>::quiet_NaN())
: y(std::numeric_limits<double>::quiet_NaN())
: z(std::numeric_limits<double>::quiet_NaN())
{ }
Users probably won't be setting x, y, and z to (NOT A NUMBER) intentially.
Primarily, i want to manually assign 0x000000 address to any variable(int or double or char) without using pointers. any suggestions?
That's not what you want. What you want is the ability to detect whether a variable has been set or not.
Others have suggested things like using a specific floating-point value to detect the uninitialized state, but I suggest employing Boost.Optional. Consider:
class CS
{
private:
boost::optional<double> x;
boost::optional<double> y;
boost::optional<double> z;
}
boost::optional either stores the type you give to the template parameter or it stores nothing. You can test the difference with a simple boolean test:
if(x)
{
//Has data
}
else
{
//Has not been initialized
}
The downside is that accessing the data is a bit more complex:
x = 5.0; //Initialize the value. x now has data.
y = 4.0 * x; //Fails. x is not a double; it is an optional<double>.
y = 4.0 * (*x); //Compiles, but only works at runtime if x has a value.
You have several options:
Use pointers.
Use a boolean flag alongside each variable indicating whether the variable has been set.
If the range of allowable values is limited, you could use a special value to stand for "not set". For double, a not-a-number is often a natural candidate. For int and char it's often more tricky to pick a good value.
None of these options is indisputably better than the other two as they involve different tradeoffs. Take your pick.
Why can't you simply do this:
class CS
{
public:
// Constructs a CS initialized to 0, 0, 0
CS() : x(0), y(0), z(0), is_initialized(false) {}
// User defined values
CS(double newX, double newY, double newZ) : x(newX), y(newY), z(newZ), is_initialized(true) {}
private:
double x;
double y;
double z;
// If you need to know that this was initialized a certain way, you could use this suggestion from the comments:
bool is_initialized;
}
If I understand correctly, you want to be able to tell the difference between an invalid, default constructed CS and a valid one with values (0.0, 0.0, 0.0). This is exactly what boost::optional http://www.boost.org/doc/libs/1_47_0/libs/optional/doc/html/index.html is for.
You can't really represent it in the same number of bits without having a sentinel. If 0 is a valid number, then you can't use it. If you try and foist null handling into a value type you will have fundamentally incorrect and unmaintainable code.
When handling nulls properly you would expect to see an interface like this:
struct foo {
virtual ~foo() {}
virtual bool getX(double &val) = 0;
virtual bool getY(double &val) = 0;
virtual bool getZ(double &val) = 0;
};
The implementation can have a flag that it checks before access.
void some_func(foo *f) {
double x, y, z;
if (f->getX(x) && f->getY(y) && f->getZ(z)) {
cout << x << ", " << y << ", " << z << endl;
} else {
throw std::logic_error("expected some values here");
}
}
You don't want to use an invalid value and not know it. Having to check the return values is tedious obviously, but it gives you the most control. You could also have helpers or overloads that would throw if they weren't valid.
struct bar {
double getX() {
if (!valid)
throw std::logic_error("bar is not valid");
return x;
}
bool valid;
double x, y, z;
}
For me, the difference between foo and bar is that low level code handling the data shouldn't enforce a policy of whether the data is there or not. At higher levels of abstraction you can and should have expectations of whether the data should valid when you go to use it. The both can exist in a system, but foo is necessary.
One way to get the semantics of what you want would be to have the datatype of the coordinates be a type that carries with it a value indicating whether it has been assigned. Something like this.
template<typename T>
class CoordinateValue {
public:
CoordinateValue() : uninitialized(true), val(0) {}
CoordinateValue(T x) : uninitialized(false), val(x) {}
void setVal(T x) {val = x; uninitialized= false}
// Trivial getters
private:
T val;
bool uninitialized;
};
I'd prefer something like this over cuter methods unless memory is really scarce for some reason.
If the coordinates are either all default or all set, then you can have a single flag rather than a coordinate datatype that includes the flag.
I want that the user can create a CS (0, 0, 0). In the constructor i
want to initialise the address of x, y & z to NULL. this is to
differentiate between the user defined (0, 0, 0) & the default value.
I am creating the objects of CS dynamically, so there is no point in
using the following code:
This is the problem. Firstly, default value? What default value? Why should there be a default value? That's wrong. And secondly, it's fundamentally impossible for you to change the address of any variable.
What you want cannot be done and even if it could, it would be a horrendously bad idea.
You can't change the address of a variable. And you can't assign pointer values (like NULL, or nullptr in C++) to a variable of a non-pointer type, such as double.

Array of values within an ENUM?

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.