How to deal with arrays (declared on the stack) in C++? - c++

I have a class to parse a matrix that keeps the result in an array member:
class Parser
{
...
double matrix_[4][4];
};
The user of this class needs to call an API function (as in, a function I have no control over, so I can't just change its interface to make things work more easily) that looks like this:
void api_func(const double matrix[4][4]);
The only way I have come up with for the caller to pass the array result to the function is by making the member public:
void myfunc()
{
Parser parser;
...
api_func(parser.matrix_);
}
Is this the only way to do things? I'm astounded by how inflexible multidimensional arrays declared like this are. I thought matrix_ would essentially be the same as a double** and I could cast (safely) between the two. As it turns out, I can't even find an unsafe way to cast between the things. Say I add an accessor to the Parser class:
void* Parser::getMatrix()
{
return (void*)matrix_;
}
This will compile, but I can't use it, because there doesn't seem to be a way to cast back to the weirdo array type:
// A smorgasbord of syntax errors...
api_func((double[][])parser.getMatrix());
api_func((double[4][4])parser.getMatrix());
api_func((double**)parser.getMatrix()); // cast works but it's to the wrong type
The error is:
error C2440: 'type cast' : cannot convert from 'void *' to 'const double [4][4]'
...with an intriguing addendum:
There are no conversions to array types, although there are conversions to references or pointers to arrays
I can't determine how to cast to a reference or pointer to array either, albeit that it probably won't help me here.
To be sure, at this point the matter is purely academic, as the void* casts are hardly cleaner than a single class member left public!

Here's a nice, clean way:
class Parser
{
public:
typedef double matrix[4][4];
// ...
const matrix& getMatrix() const
{
return matrix_;
}
// ...
private:
matrix matrix_;
};
Now you're working with a descriptive type name rather than an array, but since it's a typedef the compiler will still allow passing it to the unchangeable API function that takes the base type.

Try this. It compiles cleanly on gcc 4.1.3:
typedef double FourSquare[4][4];
class Parser
{
private:
double matrix_[4][4];
public:
Parser()
{
for(int i=0; i<4; i++)
for(int j=0; j<4; j++)
matrix_[i][j] = i*j;
}
public:
const FourSquare& GetMatrix()
{
return matrix_;
}
};
void api_func( const double matrix[4][4] )
{
}
int main( int argc, char** argv )
{
Parser parser;
api_func( parser.GetMatrix() );
return 0;
}

I've used a union like this to pass around matrices in the past:
union matrix {
double dflat[16];
double dmatr[4][4];
};
Then pass a pointer in to your setter and copy the data into the matrix in your class.
There are ways of handling this otherwise (that are more generic), but this solution tends to be the cleanest in the end, in my experience.

I thought matrix_ would essentially be the same as a double**
In C there are true multi-dimensional arrays, not arrays of pointers to arrays, so a double[4][4] is a contiguous array of four double[4] arrays, equivalent to a double[16], not a (double*)[4].
There are no conversions to array types, although there are conversions to references or pointers to arrays
Casting a value to a double[4][4] would attempt to construct one on the stack - equivalent to std::string(parser.getMatrix()) - except that the array doesn't supply a suitable constructor. You probably did't want to do that, even if you could.
Since the type encodes the stride, you need a full type (double[][] won't do). You can reinterpret cast the void* to ((double[4][4])*), and then take the reference. But it's easiest to typedef the matrix and return a reference of the correct type in the first place:
typedef double matrix_t[4][4];
class Parser
{
double matrix_[4][4];
public:
void* get_matrix () { return static_cast<void*>(matrix_); }
const matrix_t& get_matrix_ref () const { return matrix_; }
};
int main ()
{
Parser p;
matrix_t& data1 = *reinterpret_cast<matrix_t*>(p.get_matrix());
const matrix_t& data2 = p.get_matrix_ref();
}

To elaborate on the selected answer, observe this line
const matrix& getMatrix() const
This is great, you don't have to worry about pointers and casting. You're returning a reference to the underlying matrix object. IMHO references are one of the best features of C++, which I miss when coding in straight C.
If you're not familiar with the difference between references and pointers in C++, read this
At any rate, you do have to be aware that if the Parser object which actually owns the underlying matrix object goes out of scope, any code which tries to access the matrix via that reference will now be referencing an out-of-scope object, and you'll crash.

Related

Is casting an address by reinterpret_cast an undefined behaviour?

I want to find a way to encapsulate a header-only 3rd party library without exposing its header files. In our other projects, we encapsulate by using void*: in the implementation, we allocate memory and assign to it, and cast to pointer of its original type when we use it. But this time, the encapsulated class is used frequently, hence dynamic allocation is unacceptable. Here is another solution I'm currently considering.
Assuming that the encapsulated class need N bytes, I will make a char array member variable of size N in the wrapper class, named data, for instance. In the implementation, when I try to assign an object of the encapsulated class to the wrapper, or forward a function call, I need to cast &data to the pointer of encapsulated class by reinterpret_cast, firstly. The char array is completely a placeholder. To make this clear, here is a sample code.
#include <iostream>
struct Inner {
void print() const {
std::cout << "Inner::print()\n";
}
};
struct Wrapper;
Inner* addressof(Wrapper&);
const Inner* addressof(const Wrapper&);
struct Wrapper {
Wrapper() {
Inner* ptr = addressof(*this);
*ptr = Inner();
}
void run() const {
addressof(*this)->print();
}
char data[1];
};
Inner* addressof(Wrapper& w) {
return reinterpret_cast<Inner*>(&(w.data));
}
const Inner* addressof(const Wrapper& w) {
return reinterpret_cast<const Inner*>(&(w.data));
}
int main() {
Wrapper wrp;
wrp.run();
}
From the view of memory, this seems make sense. But I'm sure if this is some kind of undefined behaviour.
Additionally, I want to know if there is a list of undefined behaviour. Seems like cppreference doesn't contain such thing and C++ standard specfication is really hard to understand.
What you have here is undefined behavior. The reason is when you reinterpret an object to a different type, you are not allowed to modify it until you cast it back to the original type.
In your code, you originally have the data as a char[1]. Later, in your constructor, you reinterpret_cast &data as Inner*. At this point, modifying the its value will produce undefined behavior.
What you could do however, is to first create a Inner object, then cast it and store it in the char[1]. Later you can cast the char[1] back to the Inner object and do anything with the Inner object as wanted.
So now your constructor would look like this:
Wrapper() {
Inner inner;
char* ptr = reinterpret_cast<char*>(&inner);
std::memcpy(data, ptr, 1);
}
However, if you did it like this, then you don't even need the reinterpret_cast there as you can directly memcpy from inner:
Wrapper() {
Inner inner;
std::memcpy(data, &inner, 1);
}
Better, if you have C++20, then you can and should use std::bit_cast, along with std::byte(C++17) and std::array(C++11):
struct Wrapper {
Wrapper()
: data(std::bit_cast<decltype(data)>(Inner{}))
{}
void run() const {
std::bit_cast<Inner>(data).print();
}
std::array<std::byte, 1> data;
};
Demo: https://godbolt.org/z/MaT5sasaT

how to access a series of const variables as const array

It's clear I can have:
const TYPE a();
const TYPE b();
const TYPE c();
and I can have
const TYPE all[] = {
TYPE(),
TYPE(),
TYPE(),
};
But I would like to have both - direct and array access.
The memory layout should be the same anyway. The idea of a union comes to mind. Something along the lines of:
union FOO {
struct index_t {
TYPE a;
TYPE b;
TYPE c;
} index;
TYPE all[];
};
const FOO foo;
foo.index.a;
foo.all[0];
The naive approach is to just use references in the array
const TYPE a();
const TYPE b();
const TYPE c();
const TYPE all[3] = {
a,
b,
c,
};
The questions is: Can I be sure these are only 3 instances or is there some copying going on turning them into 6?
Is there any memory overhead at all?
So which way would be the best to go?
Are both approaches feasible?
Note: Of course there is also the option to use an array of pointers - but the goal is to find a way with just references.
An array is a sequence of variables (technically objects, but the distinction is unimportant here). You don't need another one.
TYPE all[3]; // use std::array instead if you can
This is all what's needed. const is of no special importance here, add or remove it as reuired.
Now if you have a craving for syntactic sugar and want to alias all[0] as a etc, this is possible but this possibility is likely to come with a cost.
TYPE &a=all[0], &b=all[1], &c=all[2];
The compiler is likely to allocate storage for a, b and c, especially when they are members in a class (that's your cost). It may or may not optimise them away when they are static or automatic variables.
It should be emphasised that a, b and c are not needed. They simply provide alternate names for already existing objects all[i].
Another way of achieving this is as follows
inline TYPE & a() { return all[0]; } // etc
This is unlikely to have any run-time cost, as compilers are very good at optimising such trivial functions away. The downside is that you need to write a() instead of a.
The union method, even if you manage to get it working for you, is dangerous and not recommended as it necessarily invokes undefined behaviour.
You can have something like:
struct FOO {
struct INDEX {
const TYPE a; // Can even initialize in place, e.g. const int a = 8;
const TYPE b;
const TYPE c;
};
// From here on boilerplate
Index index;
FOO() : all{this} {}
struct ALL {
ALL(FOO* p): parent{p} {}
const TYPE& operator[](unsigned index) {
// Some pointer magic
return *(static_cast<TYPE*>(static_cast<void*>(parent) + index * sizeof(TYPE)));
}
FOO* parent;
};
ALL all;
};
You'll have additional memory overhead of only the parent pointer (which is negligible if you plan to have many variables). And there will also be runtime overhead - two static casts, one integer multiplication and one addition, but this will have the access syntax you aim and won't copy the variables.

Accessing a member of an object void pointer c++

I have an assignment where I have to use a linked list of node with void* as the data. I would be filling the nodes with an object. I want to know some way of accessing the members of the object after it is in the linked list, other than casting it to the class. Is it possible? Also, here's a chunk of my code just in case it helps clarify my question.
struct Node
{
void* data_;
Node* next_;
Node()
{
data_ = 0;
next_ = 0;
}
};
class Star
{
private:
char name_[ENTRY_SZ];
long temperature_;
double luminosity_;
double mass_;
double radius_;
public:
static char filePath_[ENTRY_SZ];
Star(char* name);
void SetTemperature(char* temp);
void SetLuminosity(char* lum);
void SetMass(char* mass);
void SetRadius(char* rad);
void PrintToConsole();
void AppendToFile();
};
I want to be able to call the PrintToConsole function after it is in a void*.
You cannot work with the pointee of a void* without first casting it first. If it points at a Star, for example, you could do something like this:
static_cast<Star*>(data_)->PrintToConsole(); // Haha, Star star!
That said, in C++, it's pretty unusual to store things like this. You're much better off using a template class so that you get back the type information you need.
No. You have to cast it to the appropriate object.
I would question the reason on using void pointers.
I would also suggest a dynamic cast might be better
You should cast it to the class. But if you really don't want to, you can use the offsetof macro:
The macro offsetof expands to a constant of type std::size_t, the
value of which is the offset, in bytes, from the beginning of an
object of specified type to its specified member, including padding if
any.
If type is not a standard layout type, the behavior is undefined.
If member is a static member or a member function, the behavior is
undefined.
But you should just cast it to the class.
EDIT: Ah, I see you want to access a method of the class. That's not possible. You should cast it to the class.
Since this is an assignment, you might be best to ask your teacher/mentor as to what their intents are for using a void* type in C++; void* types are not inherently bad, but there other ways of achieving similar results while maintaining language consistency.
To answer directly:
I want to know some way of accessing the members of the object after it is in the linked list, other than casting it to the class. Is it possible?
Yes it is possible, but not using the void* idiom. Using your code as an example, you would indeed have to cast to the appropriate type and be certain the types pointed to are compatible if you keep the void*, example:
struct Node
{
void* data_;
Node* next_;
Node()
{
data_ = 0;
next_ = 0;
}
};
class Star
{
public:
void PrintToConsole() {} // empty to avoid not-defined errors
};
int main() {
Node n;
n.data_ = new int(42);
static_cast<Star*>(n.data_)->PrintToConsole(); // this will compile fine, but what happens here is undefined
delete static_cast<int*>(n.data_); // can't delete void*, have to cast
return 0;
}
Again, since this is an assignment, your professor is probably just trying to teach about pointers and casting or the type system and you probably haven't learned about C++ templates, but since you asked, here's your code using templates:
template < typename T >
struct Node
{
T data_;
Node* next_;
// use member init list to construct default T object
Node() : data_(), next_(0)
{
}
};
class Star
{
public:
void PrintToConsole() {} // empty to avoid not-defined errors
};
int main() {
Node<Star*> n;
n.data_ = new Star();
n.data_->PrintToConsole(); // OK
delete n.data_; // no cast needed since data_ is a Star* type
Node<int*> n2;
n2.data_ = new Star(); // compiler error (data_ is of type int* not Star*)
n2.data_->PrintToConsole(); // compiler error (int has no member named PrintToConsole)
delete n.data_;
return 0;
}
This is just a simple example to illustrate what you were asking and it's still probably best to ask your teacher for more clarification if your confused on the topic.
Hope that can help.

Use constructor to initialize array (C++)

How do I initialize an array through a constructor?
Here is the code for a class called Sort:
private:
double unpartitionedList[];
public:
Sort(double unpartitionedList[]);
Sort::Sort(double unpartitionedList[])
{
this->unpartitionedList = unpartitionedList;
}
I'd like to be able to pass an array to the constructor and have it stored in unpartitionedList[]. Like this: Sort(array[])
As the code is now, I get a compiler error in DevC++:
"[Error] incompatible types in assignment of 'double*' to 'double[0]'"
I've tried inserting reference (&) and dereference (*) operators where I thought they were needed, but unfortunately, my attempts were unsuccessful.
Any suggestions would be greatly appreciated.
Arrays aren't assignable. You'll have to do an element-wise copy or write actual C++ code and use std::array or std::vector.
class Sort
{
private:
double unpartitionedList[];
public:
Sort(double unpartitionedList[]);
};
Sort::Sort(double unpartitionedList[])
{
this->unpartitionedList = unpartitionedList;
}
That code will not compile as arrays are not assignable. You can accomplish your goal a few different ways (depending on the requirements you haven't mentioned).
Method 1: Manual Memory Management
class Sort
{
private:
double* unpartitionedList;
std::size_t _size;
public:
Sort(double* upl, std::size_t n);
};
Sort::Sort(double* upl, std::size_t n) : unpartitionedList(upl), _size(n)
{
}
There are a few things to note here: If you intend for this class to take ownership of the memory, you will have to properly manage it (e.g. free the memory in the destructor, and provide a proper copy-constructor that will perform a deep-copy). Because of the memory management requirements, this method is not recommended if not absolutely necessary.
Method 2/3: STD Containers
class Sort
{
private:
std::vector<double> _upl;
// or
// std::array<double, SIZE> upl; // with a constant SIZE defined
public:
Sort(const std::vector<double>& upl);
};
Sort::Sort(const std::vector<double>& upl) : _upl(upl)
// Sort::Sort(const std::array<double, SIZE>& upl) : _upl(upl)
{
}
This will remove the memory management requirement. std::vector will allow you to size the array at runtime. std::array is a thin wrapper around a C-style array (and must be sized at compile time).

Overloading function call operator and assignment

In a project of mine, I'm writing a wrapper for std::vector. I'm doing this because I am using homogeneous coordinates and for some operations it's just easier to temporarily 'forget' the fourth coordinate.
Now I stumbled upon a problem. I have loads of assignments like the following:
Vector v;
v(0) = 5;
v(1) = 6;
and so on. I also want to do the following:
double x;
x = v(0);
For that last thing, I can overload the () operator, but how would implement the first thing? (the zero and one being an index).
Just return reference.
class Vector
{
int data[4];
int & operator() (int index) { return data[index]; }
};
Return a non-const reference to the element to be modified.
Two things-
You should probably be overloading operator[] to do this rather than operator(), since it's the more natural operator here. operator() is used to create function objects, while operator[] is the operator meaning "pick out the element at this position."
You can support assignment to the result of operator[] / operator() by having the function return a reference to the value that should be written to. As a simple example, here's some code that represents a class wrapping a raw array:
(code here:)
class Array {
public:
int& operator[] (unsigned index);
int operator[] (unsigned index) const;
private:
int array[137];
};
int& Array::operator[] (unsigned index) {
return array[index];
}
int Array::operator[] (unsigned index) const {
return array[index];
}
The second of these functions is a const overload so you can have const Array read but not write values.
In the standard libraries, such things are implemented by having operator() (well, actually usually operator[]) return type double &. By returning a reference to a double, you can assign to or from it.
However, are you sure you want to wrap this around std::vector? This class is not a vector in the mathematical sense; it's much like a Java ArrayList, and so not at all efficient for small structures. Usually when I'm writing my own vector classes I'm planning on having lots of them around, so I implement a class from scratch on top of a static array.