Structs - expression must be a modifiable value - c++

I'm new to structs and I'm struggling a bit.
I have the following struct:
typedef struct
{
CHAR_t bWpId[10];
CHAR_t bWpDescr[25];
UINT16_t wCoA;
sUtmCoordinate_t Coordinate;
} sWaypoint_t;
typedef struct
{
sWaypointListElement Element[cMAX_WAYPOINTS];
UINT8_t bHead;
UINT8_t bTail;
UINT8_t bNumElements;
} sWaypointList;
Now each waypoint is an element in a waypointlist which is also a struct.
class CWaypointList
{
private:
sWaypointList WaypointList;
}
Now my question is how do I read in values in each element of the struct without writing accessors? Is accessors the only way to access the data within a private struct?
If I do it like this I get the error : expression must be a modifiable value.:
element.bWpId = {'0','0','0','0','0','0','0','0','0','1'};

You can't use that syntax to initialize an array outside of the arrays definition. You have to fill in all values manually.
Fortunately there are standard C++ functions to do that for use, like std::fill:
std::fill(std::begin(element.bWpId), std::end(element.bWpId), '0');
element.bWpId[9] = '1';
You can of course make a constructor for the sWaypoint_t structure, and initialize the array in that:
typedef struct sWaypoint_s
{
CHAR_t bWpId[10];
CHAR_t bWpDescr[25];
UINT16_t wCoA;
sUtmCoordinate_t Coordinate;
sWaypoint_s()
: bWpId{'0','0','0','0','0','0','0','0','0','1'}
{}
} sWaypoint_t;
The problem with this is that it requires a C++11 capable compiler.

In C++ you can not list-initialise array that has already been constructed. Same applies for list-initialising structures.
Using std::fill is one way, but I dislike its obscurity. Instead you can try using this helper function:
template <class T, size_t Size>
void copy_array(T (&dst)[Size], const T (&src)[Size])
{
std::copy(src, src+Size, dst);
}
Now you can "assign" any array. In the case of element.bWpId:
CHAR_t temp[] = {'0','0','0','0','0','0','0','0','0','1'};
copy_array(element.bWpId, temp);
The function will compile-time check arrays types and sizes, so it leaves no opportunity for a mistake. Which is a huge advantage over explicit std::fill and manual indexing.
All that provided you don't have access to C++11 compiler. If you have, just change the bWpId to std::array<Char_t, 10> and then you can list-initialise it anytime you want.

I used sprintf(element.bId,'0');

Related

Heterogeneous array implementation

I would appreciate your help!
Which data structure is used to implement heterogeneous array in C or C++ ? The array may contain any standard data types like int,float, char, string etc...
As ravi mentions, the appropriate data structure is called a tag-union (also called variant record). One way to implement it is this:
typedef union {
int tag;
struct {
int tag;
int val;
} int_;
struct {
int tag;
double val;
} double_;
} object;
Then you can make an array of these.
object arr[5];
You use the tag field to indicate which union member is in use. Typically with an enum.
enum type { INT, DOUBLE };
Then set the tag when creating the object, and check the tag before accessing. This can be encapsulated by using constructor functions.
object new_int(int i){
object ret;
ret.tag = INT;
ret.int_.val = i;
return ret;
}
object new_double(double d){
object ret;
ret.tag = DOUBLE;
ret.double_.val = d;
return ret;
}
And you usually want to use a switch on the tag for accessing, writing a different case for each type.
void print_object(object x){
switch(x.tag){
case INT: printf("%d\n", x.int_.val); break;
case DOUBLE: printf("%f\n", x.double_.val); break;
}
}
Or in some circumstances, you may want to fold the array into a single type so it can be accessed without checking the tag each time.
for (i = 0; i < sizeof arr/sizeof*arr; i++)
if (arr[i].tag == INT)
arr[i] = new_double(arr[i].int_.val);
There is no such array in c++ which can store elements of different types nor there is container in stl. Although there's one way to store different element in a container but condition is those types should be related through inheritance.
In C there's a concept called tagged union which can store different types giving tag as a means to specify which variable is actually there.
One more way to do this is using an array of void* pointers. Although that would be quite ugly C++. This would not be truly heterogeneous as you are using a type of pointer that any pointer can be cast into. It is similar to making a collection of base class type and then storing objects of derived classes.
This I got from Stroustrup article:-
If you need a heterogeneous container in C++, define a common interface for all the elements and make a container of those. For example:
class Io_obj { /* ... */ }; // the interface needed to take part in object I/O
vector<Io_obj*> vio; // if you want to manage the pointers directly
vector< Handle<Io_obj> > v2; // if you want a "smart pointer" to handle the objects
Apart from that Boost::Any can also be used:-
vector<Any> v;
I guess you could keep an array of pointers to anything
void* stuff[size];
const char* str = "hello";
int x = 20;
int *array = malloc(sizeof(int) * 5);
stuff[0] = str;
stuff[1] = &x;
stuff[2] = array;
Alternatively, an array of unions if you knew all the types before hand.

Converting a struct to an array

As programming becomes more complex, and the need to perform operations on struct data becomes visible. Is there a conversion method for converting a struct type into an array of its members such that:
struct FooDesc Foo{
int num_Foo;
int num_Bar;
int GreenFoo;
};
can be represented by:
int Bar[2];
Or better, dynamically as:
vector<int> Bar;
The goal is to convert or re-represent the data struct as an iteratable form, without the excessive use of the assignment operator.
You could use unnamed structs to make a hybrid struct where its member could be treated as an array:
struct Foo {
union {
struct {
int x;
int y;
int z;
};
struct {
int array[3];
};
};
};
LIVE DEMO
Note however, that unnamed struct comes from C11 and its not a standard C++ feature. It is supported as an extension though by GCC as well Clang.
If your structs are POD then you might consider using std::tuple instead of structs. You could then use various template facilities to work through the members of the tuple.
Here is a simple example that prints the elements of a tuple - using boost::fusion::tuple instead of the std::tuple since it has many more tuple-manipulating facilities available:
#include <boost/fusion/tuple.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <iostream>
struct Printer {
template<typename T>
void operator()(const T &t) const {
std::cout << t << std::endl;
}
};
int main(int argc, const char * argv[])
{
boost::fusion::tuple<int, int, int, int, float> t =
boost::fusion::make_tuple(3, 5, 1, 9, 7.6f);
boost::fusion::for_each(t, Printer());
return 0;
}
You could include these in unions with the struct but you'd want to do some testing to ensure proper alignment agreement.
The upside is that these manipulations are very fast - most of the work is done at compile time. The down-side is that you can't use normal control structs like indexing with runtime indices - you'd have to build an abstraction layer around that as the normal get<i>(tuple) accessor requires that i be a compile time constant. Whether this is worth the complexity depends strongly on the application.
How about:
vector <Foo> Bar;
You can then add instances of your struct and then access each element as desired, using an array-like format.
See this related question for further information:
Vector of structs initialization
Upon re-reading your question a few times, I think I mis-understood your intent and answered the "wrong question". You can make an array of your struct as mentioned above and index it as an array, but I don't believe it is quite as simple as that to make each struct element a different element of an array. If you are looking to make an array of structs, my answer should help. If you are looking to make each element of your struct an element of your array, 40two's answer should help you out.

Passing array of vectors as a function parameter (values will not change)

I have an array of vectors in one class:
class MeasurementData
{
private:
std::vector<double> m_measuredStrengths[3];
}
And I would like a function of another class to examine that and pass back an integer based on the analysis, e.g.
int CStrengthAnalyser::GetBestFit(std::vector<double> measuredStrengths[3])
{
int bestFit = -1;
// do stuff
return bestFit;
}
And I'm a little confused by the best practice for passing this kind of object around, plus setting up my receiving function to guarantee no changes to the original data.
Is my function declaration OK as-is, or do I need to add some best practice tweaks?
The function you have right now is the same function as:
int CStrengthAnalyser::GetBestFit(std::vector<double> * measuredStrengths )
So it can definitely modify the vectors. If you're always dealing with an array of size 3 you can take a const reference to an array of size 3.
int CStrengthAnalyser::GetBestFit(std::vector<double> const (&measuredStrengths)[3])
Or if you want to make it more generic:
struct CStrengthAnalyser
{
// ...
template<std::size_t N>
int GetBestFit(std::vector<double> const (&measuredStrengths)[N])
{ ... }
};
In this case the member function definition must appear in the header (or, to be precise, the definition must be visible to the compiler at the callsite).
If you want to avoid the ugly reference to array syntax you could change the MeasurementData definition to contain a std::array<std::vector<double>, 3> instead of a plain C array. Then passing a reference to that is cleaner
int CStrengthAnalyser::GetBestFit(std::array<std::vector<double>, 3> const& measuredStrengths)
And finally, you could also deduce the size of the std::array using a function template as shown previously.
I would suggest that you use a vector of vectors here, like
vector<vector<double> > your_measure(3);
When you pass it into another function, you can use the key word const to it, like
my_fun(vector<vector<double> > const & your_vec_vec);

Removing potentially redundant template parameters when loading a binary file into Eigen matrix

I want to read a plain binary file containing a number of unsigned 16-bit integers into an Eigen matrix, and I wrote a templated utility to do this. This is what the caller looks like:
Matrix<uint16_t, Dynamic, Dynamic> data;
int retval = read_data<Matrix<uint16_t, Dynamic, Dynamic>, uint16_t>(
argv[1], data);
And here's what read_data looks like:
template <typename Derived, typename Scalar> // Per #Jarod42, get rid of Scalar here (*)
int read_data(const char* const fname, MatrixBase<Derived>& data) {
// (*) If we don't have Scalar as a template, just uncomment this:
// typedef typename Derived::Scalar Scalar;
ifstream fin(fname, ios::binary);
if (!fin) {
return 2;
}
fin.seekg(0, fin.end);
long long bytes = fin.tellg();
if (bytes % sizeof(Scalar) != 0) {
// The available number of bytes won't fill an even number of Scalar
// values
return 3;
}
long long nscalars = bytes / sizeof(Scalar);
// See http://forum.kde.org/viewtopic.php?f=74&t=107551
MatrixBase<Derived>& data_edit = const_cast<MatrixBase<Derived>&>(data);
data_edit.derived().resize(nscalars, 1);
Scalar* buffer = new Scalar[nscalars]; // Switched to vector per #Casey
fin.seekg(0, fin.beg);
fin.read(reinterpret_cast<char*>(buffer), bytes);
if (!fin) {
// All data not read. fin.gcount() will indicate bytes read.
return 4;
}
for (long long idx = 0; idx < nscalars; ++idx) {
data_edit(idx) = buffer[idx];
}
return 0;
}
In brief,
the file is opened,
its size is obtained,
an array is dynamically allocated to store all the data,
the file is read into the array,
the array's contents are copied into the matrix.
This is reasonable and it works (though I'm open to suggestions for improvements), but I think the function has one too many template parameters, and the function call in the caller is just too verbose. I think there should be a way to eliminate the second template parameter, which only serves to tell read_data the number of bytes per scalar (2 in the case of uint16_t), and which I believe should be inferrable using the first template parameter.
Questions Is there a way to eliminate the seemingly redundant second template parameter to read_data?
Also, is my approach of passing in a matrix reference only to resize it in the read_data function (using the verbose and confusing idiom of creating a modifiable reference to the matrix in order to resize it via derived()) the right way to proceed? I realize this dynamically allocates memory, which is fine, but I think it is not doing anything wasteful---correct?.
(Discussion Is there other improvements to this code one would like to see? I'm a C or Python numerical coder; in C, I'd just deal with void* arrays and pass an extra function argument telling the function the size of each scalar; with Python I'd just do numpy.fromfile('path/to/file.bin', dtype=numpy.uint16) and be done with it. But I'd like to do it right by Eigen and C++.)
NB. I use matrixes instead of vectors because I'll be resizing them into rectangular matrixes later.
NB2. In Fixed Sized Eigen types as parameters the notion of templating the function using the scalar type is promoted. I am not averse to this approach, I chose to pass read_data a matrix reference instead of making it return a Matrix object because I wanted integer return values indicating errors---though now I realize I ought to make those exceptions.
NB3. In c++ check for nested typedef of a template parameter to get its scalar base type an elaborate set of helper classes is used to, I think, achieve a similar effect for templated classes. I'm curious if a simpler approach can be used here, for a templated function.
NB4. A simple improvement that I'm aware of is typedeffing Matrix<uint16_t, Dynamic, Dynamic> to reduce verbosity.
I think that Matrix<uint16_t, Dynamic, Dynamic> should have a typedef to retrieve uint16_t. If so, you may write as first line (assuming it is type):
typedef typename Derived::type Scalar;
If there is no typedef, you may write a traits for that:
template <typename> struct matrix_type;
template <typename T, typename U1, typename U2>
struct matrix_type<Matrix<T, U1, U2> >
{
typedef T type;
typedef U1 type1;
typedef U2 type2;
};
And then write
typedef typename matrix_type<Derived>::type Scalar;
Note:
If you have written the parameters in the other order
template <typename Derived, typename Scalar>
int read_data(const char* const fname, MatrixBase<Derived>& data);
you may write (as the last parameter may be deduced):
Matrix<uint16_t, Dynamic, Dynamic> data;
int retval = read_data<uint16_t>(argv[1], data);
And now that the parameter is obsolete, you may write directly:
Matrix<uint16_t, Dynamic, Dynamic> data;
int retval = read_data(argv[1], data);
You may want to look at map in eigen. It takes a chuck a memory directly.
TutorialMapClass.html">http://eigen.tuxfamily.org/dox/group_TutorialMapClass.html
To construct a Map variable, you need two other pieces of information: a pointer to the region of memory defining the array of coefficients, and the desired shape of the matrix or vector. For example, to define a matrix of float with sizes determined at compile time, you might do the following:
Map mf(pf,rows,columns);

What is the safe way to fill multidimensional array using std::fill?

Here is what I am using:
class something
{
char flags[26][80];
} a;
std::fill(&a.flags[0][0], &a.flags[0][0] + 26 * 80, 0);
(Update: I should have made it clear earlier that I am using this inside a class.)
The simple way to initialize to 0 the array is in the definition:
char flags[26][80] = {};
If you want to use std::fill, or you want to reset the array, I find this a little better:
char flags[26][80];
std::fill( &flags[0][0], &flags[0][0] + sizeof(flags) /* / sizeof(flags[0][0]) */, 0 );
The fill expressed in terms of the array size will allow you to change the dimensions and keep the fill untouched. The sizeof(flags[0][0]) is 1 in your case (sizeof(char)==1), but you might want to leave it there in case you want to change the type at any point.
In this particular case (array of flags --integral type) I could even consider using memset even if it is the least safe alternative (this will break if the array type is changed to a non-pod type):
memset( &flags[0][0], 0, sizeof(flags) );
Note that in all three cases, the array sizes are typed only once, and the compiler deduces the rest. That is a little safer as it leaves less room for programmer errors (change the size in one place, forget it in the others).
EDIT: You have updated the code, and as it is it won't compile as the array is private and you are trying to initialize it externally. Depending on whether your class is actually an aggregate (and want to keep it as such) or whether you want to add a constructor to the class you can use different approaches.
const std::size_t rows = 26;
const std::size_t cols = 80;
struct Aggregate {
char array[rows][cols];
};
class Constructor {
public:
Constructor() {
std::fill( &array[0][0], &array[rows][0], 0 ); // [1]
// memset( array, 0, sizeof(array) );
}
private:
char array[rows][cols];
};
int main() {
Aggregate a = {};
Constructor b;
}
Even if the array is meant to be public, using a constructor might be a better approach as it will guarantee that the array is properly initialized in all instances of the class, while the external initialization depends on user code not forgetting to set the initial values.
[1] As #Oli Charlesworth mentioned in a comment, using constants is a different solution to the problem of having to state (and keep in synch) the sizes in more than one place. I have used that approach here with a yet different combination: a pointer to the first byte outside of the bidimensional array can be obtained by requesting the address of the first column one row beyond the bidimensional array. I have used this approach just to show that it can be done, but it is not any better than others like &array[0][0]+(rows*cols)
What is the safe way to fill multidimensional array using std::fill?
The easy default initialization would be using braced inilization.
char flags[26][80]{};
The above will initialize all the elements in the flags to default char.
2-D Array filling using std::fill or std::fill_n
However, in order to provide different value to initialize the above is not enough. The options are std::fill and std::fill_n. (Assuming that the array flags is public in your class)
std::fill(
&a.flags[0][0],
&a.flags[0][0] + sizeof(a.flags) / sizeof(a.flags[0][0]),
'0');
// or using `std::fill_n`
// std::fill_n(&a.flags[0][0], sizeof(a.flags) / sizeof(a.flags[0][0]), '1');
To generalize this for any 2d-array of any type with any initializing value, I would suggest a templated function as follows. This will also avoid the sizeof calculation of the total elements in the array.
#include <algorithm> // std::fill_n, std::fill
#include <cstddef> // std::size_t
template<typename Type, std::size_t M, std::size_t N>
constexpr void fill_2D_array(Type(&arr2D)[M][N], const Type val = Type{}) noexcept
{
std::fill_n(&arr2D[0][0], M * N, val);
// or using std::fill
// std::fill(&arr2D[0][0], &arr2D[0][0] + (M * N ), val);
}
Now you can initialize your flags like
fill_2D_array(a.flags, '0'); // flags should be `public` in your class!
(See Live Online)
3-D Array filling using std::fill or std::fill_n
Adding one more non-template size parameter to the above template function, this can be brought to 3d-arrays as well
#include <algorithm> // std::fill_n
#include <cstddef> // std::size_t
template<typename Type, std::size_t M, std::size_t N, std::size_t O>
constexpr void fill_3D_array(Type(&arr3D)[M][N][O], const Type val = Type{}) noexcept
{
std::fill_n(&arr3D[0][0][0], M * N * O, val);
}
(See Live Online)
it is safe, a two-dimensional array is an array of arrays. Since an array occupied contiguous storage, so the whole multidimensional thing will too. So yeah, it's OK, safe and portable. Assuming you are NOT asking about style, which is covered by other answers (since you're using flags, I strongly recommend std::vector<std::bitset<80> > myFlags(26))
char flags[26][80];
std::fill((char*)flags, (char*)flags + sizeof(flags)/sizeof(char), 0);
Is char[80] supposed to be a substitute for a real string type? In that case, I recommend the following:
std::vector<std::string> flags(26);
flags[0] = "hello";
flags[1] = "beautiful";
flags[2] = "world";
// ...
Or, if you have a C++ compiler that supports initialization lists, for example a recent g++ compiler:
std::vector<std::string> flags { "hello", "beautiful", "world" /* ... */ };