is there an array bitshift operator in C++? - c++

Is there? for example:
unsigned long long myarray[4];
myarray <<= (8*sizeof(unsigned long long));
myarray[3] = my_new_value_at_front;
would be equivalent to:
unsigned long long myarray[4];
myarray[0] = myarray[1];
myarray[1] = myarray[2];
myarray[2] = myarray[3];
myarray[3] = 0;
myarray[3] = my_new_value_at_front;
if not are there any containers which support a constant N elements and when you push a new one at [N-1] then everithing will be shifted?

No. There is not. But I can recommend something better. Try std::deque.
std::deque<unsigned long long> mydeque {0, 1, 2, 3};
for (const auto& x : mydeque )
std::cout << x << " ";
std::cout << std::endl;
mydeque.pop_front();
mydeque.push_back(4);
for (const auto& x : mydeque )
std::cout << x << " ";
std::cout << std::endl;
With std::deque, you can use memeber function pop_front to remove the first element, and push_back to insert at the back.

There's no operator but you can do:
std::rotate(myarray, myarray + N, myarray + 4);
where N is the index of the element that should be moved to the start, and the other arguments are the begin and end. You could overwrite later elements afterwards if you wanted.
In your case:
std::rotate(myarray, myarray + 1, myarray + 4);
myarray[3] = my_new_value_at_front;

This is not possible with naked arrays but considering you are using an integral type you can use std::valarray which includes shift and circular shift functions that should meet your requirements. It provides random access much like a naked array but with additional functionality thrown in.

Related

Is there a function for accessing the amount of elements that have a value in an std::array?

In C++, assume I have an std::array<std::optional<std::int>, 5> array. Let's say I set the first 3 elements to be of a certain value. Is there a function that when passed array returns 3 (i.e. Returns the number of elements that has an assigned value)? Or is there anyway to improve the std::array so that it supports this functionality? I appreciate your help.
P.S. Guaranteed: The array's elements are always consecutive.
For instance,
std::array<std::optional<std::int>, 5> arr;
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
arr[3] = 4;
cout << func(arr) << endl; // Returns 4 in this case
Edit 1. I already knew about std::count, but I do not know how to check if an element is defined. Also, the array could be of any type.
Edit 2. What if I used std::optional? How could I do that, then?
I already knew about std::count, but I do not know how to check if an element is defined.
You can use std::count_if() for this, eg
std::array<std::optional<int>, 5> arr;
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
arr[3] = 4;
auto cnt = std::count_if(arr.begin(), arr.end(),
[](const auto &elem){ return elem.has_value(); }
);
std::cout << cnt << std::endl; // Returns 4 in this case

C++ Iterator range using pointers to an array

Question
I do not want to pass the size of the array as an index parameter.
For my merge_sort, I want to optimize my parameters using the iterator range concept. I can't seem to figure out how to deference the iterator range and access my array. I can deference to access the indices like low and high in recursive_merge_sort, but there does not seem to be an intuitive way to access the array itself. I've been using this great guide on C++ Pointers and Arrays as a starting point.
My Merge Sort C++11 C++17 question brought this concept to light and I like the idea of using iterator ranges to reduce the number of parameters for my sort.
Code
void recursive_merge_sort(int* low, int* high) {
// deference to get starting index "low" and ending index "high"
if(*(low) >= *(high) - 1) { return; }
int mid = *(low) + (*(high) - *(low))/2;
// what's the correct syntax to access my array from the iterator range
// int* d = some how deference low or how to get the data array they iterate on
recursive_merge_sort_v(d + low, d + mid);
recursive_merge_sort_v(d + mid, d + high);
merge(d + low, mid, d + high);
// delete d;
}
void merge_sort(int* data) {
// what's the correct syntax to access my array from the passed in iterator range
// is this event possible? incorrect syntax below
recursive_merge_sort(data + 0, data + std::size(*(data)));
}
int main()
{
int data[] = { 5, 1, 4, 3, 65, 6, 128, 9, 0 };
int num_elements = std::size(data);
std::cout << "unsorted\n";
for(int i=0; i < num_elements; ++i) {
std::cout << data[i] << " ";
}
merge_sort(data);
std::cout << "\nsorted\n";
for(int i=0; i < num_elements; ++i) {
std::cout << data[i] << " ";
}
}
Comment section Solution from the bayou
Remy Lebeau: "When you pass an array by pointer, you lose all information about it. You can't get back to the original array given only a pointer/iterator, as dereferencing will only give you a single element of the array, not the array itself. When passing an array by pointer, you have no choice but to pass the array size as another parameter. Otherwise, pass the array by reference instead, and if you need to support arrays of different sizes then use a template so the compiler can deduce the array size for the reference."
Iterators are modeled to act like pointers. They have the same type of overloaded operators: dereferencing and increment at the very least (some also have decrement, random access, etc.).
The most advanced iterator interface is random access, which functions exactly like a raw pointer (by design).
So all (raw) pointers are basically random access iterators into a C-style (contiguous) array. Look at the following to visualize begin/end iterators for a C-style array:
int vals[] = { 0, 1, 2, 3, 4 };
int *begin = vals;
int *end = vals + 5;
v vals[]
0 1 2 3 4 ...
^ begin ^ end (1 past the end of array)
vals[2] == begin[2]
vals[4] == begin[4]
etc.
So basically, you just treat the begin iterator as the front of the array, and you just don't dereference anywhere before the begin iterator, nor at or past the end iterator, as standard C++ convention dictates the end iterator is 1 past the end of the range.
Here's an example of using pointers like iterators:
void print(int *begin, int *end)
{
// for each element in the range (starting at begin, up to but not including end)
for (; begin != end; ++begin)
{
// print the element
std::cout << *begin << '\n';
}
}
int main()
{
// declare a C-style array
int arr[] = { 10, 5, 2, 6, 20 };
// for the sake of example, print only the middle 3 elements
// begin = arr + 1
// end = arr + 4
print(arr + 1, arr + 4);
return 0;
}

Selective shallow copy from one array to another

Assuming I have 2 array of different size i.e
int arr[] = {0,1,2,3,4,5,6,7,8,9};
int *arr2 = new int[5];
I want to shallow copy some of them,
Deep copy equivalent would be
int j =0;
if(!(i%2))
{
arr2[j]=arr[i];
j++;
}
Right now a print of arr2 will output : 0, 2, 4, 6 ,8
The reason I want to shallow copy is because I want arr2 to update with any changes to arr.
That is if I loop and square all the elements in arr
I want arr2 to output : 0, 4, 16, 36 ,64
These 2 arrays are part of the same class, one is my polygonal information, and the other part is data driven. arr is actually 4000+ elements in size, and arr2 is close to 3000. At the moment my algorithm works great with deep copy. but because I need to deep copy 3000 elements per update frame, i am wasting resources and was wondering if i could somehow do this via shallow copy so I don't have to have to update arr2 every frame. The way my code needs it to work, arr actually has repeated values of arr2. arr2 is a list of points that is animated. then the data is duplicated to arr which hold the positional data for vertices. this is because arr contains multiple bezier patches, some of them share one edge or more with another patch. but i want that to be ignored when animating else there are breaks in the surface.
It is important that the copy involves indices like
arr2[j]=arr[i];
because that is how my code is setup.
And that the operation be low load.
You will need an array of integer pointers for that.
int *arr2[5];
for (int i = 0, j = 0; i < 10; i++) {
if (!(i%2)) {
arr2[j]= &arr[i];
j++;
}
}
So you need to set each element of arr2 to point to corresponding element in arr by arr2[j]= &arr[i];
When you need to access element in arr2, you call some thing like: int a = *arr2[j];
Later on let say you change arr[0] to 10 arr[0] = 10; then int a = *arr2[0]; will give you 10.
As an alternative to the pointer array approach, here's a crude C++03 example of how to this programmatically. Which one is better depends on how complex the operator[] here needs to be in the real use case, and how much smaller the 2nd array is (ie. how much extra memory it needs, causing cache misses etc).
#include <iostream>
class c_array_view {
public:
c_array_view(int *array) : array_(array) {}
int& operator[](size_t index) { return array_[index*2]; }
static size_t convert_length(size_t original) { return original / 2; }
private:
int *array_;
};
int main()
{
int arr[] = {0,1,2,3,4,5,6,7,8,9};
size_t arr_len = sizeof arr / sizeof arr[0];
c_array_view arr2(arr);
size_t arr2_len = arr2.convert_length(arr_len);
for(unsigned i = 0; i < arr_len; ++i) {
std::cout << "arr: " << i << " = " << arr[i] << std::endl;
}
std::cout << std::endl;
for(unsigned j = 0; j < arr2_len; ++j) {
std::cout << "arr2: " << j << " = " << arr2[j] << std::endl;
}
std::cout << std::endl;
arr2[2] = 42;
std::cout << "modifeid arr2[2] to 42, now arr[4] = " << arr[4] << std::endl;
return 0;
}
The c_array_view could be turned into a template, a nice general purpose class which would take the mapping function as a C++11 lambda, etc, this just demonstrates the principle.
if you want squares then you should not do arr2[j]=arr[i]. The correct answer would be
arr2[j]=arr[i]*arr[i];

Int array in C++

I am trying to loop through the array and get the elements inside in C++. Here is my code:
int result;
int index_array [] = {11,12,13,14,15,16,17,18,19,20};
for (int count =0; count < index_array.length() ; count++){
if(count%2 == 0){
cout << "Elements at the even index are " << index_array[count] << endl;
}
}
If I change the for loop to:
for (int count =0; count < 10 ; count++){
There is no error because my array only consists of 10 items. But if I used the .length() method, there is an error which is expression must have a class type. I have no idea what is it, as in if it is in Eclipse, there contains a more detailed error description. What might be wrong?
Updated answer
for (int count =0; count < sizeof(index_array)/sizeof(index_array [0]) ; count++){
if((count+1)%2 == 0){
cout << "Elements at the even index are " << index_array[count] << endl;
}
}
You can't call length() on int index_array[], it is a primitive array, not an object.
You could call size(), if you have, for example vector<int> index_array.
There is not .length for a plain array in C++.
Instead use std::vector and you can use method size() :
std::vector<int> index_array {11,12,13,14,15,16,17,18,19,20};
for (int count =0; count < index_array.size() ; count++){
if(count%2 == 0){
cout << "Elements at the even index are " << index_array[count] << endl;
}
}
Also in your case, you can calculate the length of the array:
int length = sizeof(index_array)/sizeof(index_array[0]);
int index_array [] = {11,12,13,14,15,16,17,18,19,20};
This is not an object that you can invoke some length() method on. Instead, it's a regular array, just like in C.
You can do one of two things.
The first is to use one of the C++ collection classes such as std::vector (adjustable size) or std::array (constant size) with their size() methods:
// C++11 syntax
std::vector<int> index_array {11,12,13,14,15,16,17,18,19,20};
// Pre C++11 syntax
int ia_src[] = {11,12,13,14,15,16,17,18,19,20};
vector<int> index_array (ia_src, ia_src + sizeof (ia_src) / sizeof (*ia_src));
std::array<int,10> index_array = {11,12,13,14,15,16,17,18,19,20};
The second is to simply treat the array as an array, in which case the length of that array can be found with the expression:
sizeof (index_array) / sizeof (*index_array)
Just be aware that this only works for arrays. If you pass that array to a function, it will decay to a pointer to the first element and sizeof will no longer work as you expect. You need to get the size while it's still an array and pass that along with it.
Arrays in c++ are not object (classes) so they don't have neither methods nor attributes.
May be you can use the Array class instead and get the size like std::array::size()

using only part of an array

I have a dynamically allocated array of float and I need to pass this array as an argument to three different functions but each function need to get a different range of the array. Is there some way I can send the array with elements 0 to 23 to one function, elements 24 to 38 to another, and elements 39 to 64 to a third function.
In some languages(like python I think) you can do something like this:
somefunction(my_array[0:23]);
somefunction(my_array[24:38]);
somefunction(my_array[39:64]);
However I am using c++ and I am not aware of any way to do this in c++.
Does anybody know how to do this?
somefunction(); is a function from an API so I can not modify the arguments it takes.
If you write the functions to operate on a pair of forward iterators rather than an array, you could just pass it like so:
somefunction1(my_array, my_array + 24);
somefunciton2(my_array + 24, my_array + 39);
somefunction3(my_array + 39, my_array + 65);
Pointers are forward iterators, and this would allow the functions to be used over parts of vectors, queues, or other STL containers as well.
The python example is making copies. If that's okay for your use case, you could do something like this (I'm swapping out your vanilla arrays for std::vector):
#include <iostream>
#include <vector>
void somefunction(std::vector<int> v) {
std::cout << "vector has " << v.size() << " elements,"
<< " first value is " << *v.begin() << ","
<< " last value is " << *(v.end()-1) << std::endl;
}
int main() {
std::vector<int> a;
for (int i=0; i<65; i++) {
a.push_back(i);
}
somefunction(std::vector<int>(a.begin(),a.begin()+23));
somefunction(std::vector<int>(a.begin()+24,a.begin()+38));
somefunction(std::vector<int>(a.begin()+39,a.begin()+65));
}
which outputs:
vector has 23 elements, first value is 0, last value is 22
vector has 15 elements, first value is 23, last value is 37
vector has 27 elements, first value is 38, last value is 64
But it sounds like you can't use std::vector, because somefunction() has a signature you can't change. Luckily, you can do similar gymnastics just manually copying parts of the array, as below:
#include <iostream>
#include <string.h>
void somefunction(int v[], int len) {
std::cout << "vector has " << len << " elements,"
<< " first value is " << v[0] << ","
<< " last value is " << v[len-1] << std::endl;
}
int main() {
int a[65];
for (int i=0; i<65; i++) {
a[i] = i;
}
int b[23];
memcpy(b, a, 23*sizeof(int));
somefunction(b, 23);
int c[15];
memcpy(c, a+23, 15*sizeof(int));
somefunction(c, 15);
int d[27];
memcpy(d, a+38, 27*sizeof(int));
somefunction(d, 27);
}
which again outputs:
vector has 23 elements, first value is 0, last value is 22
vector has 15 elements, first value is 23, last value is 37
vector has 27 elements, first value is 38, last value is 64
Your function is going to need some way to determine the size of the array anyway. I suggest you make the function take begin and end iterators, in the style of the standard library algorithms, like so:
template<typename I>
void somefunction(I begin, I end);
Then, you can call it with your array like this:
somefunction(my_array, my_array + 24);
somefunction(my_array + 24, my_array + 39);
somefunction(my_array + 39, my_array + 65);
There are two ways you could do it:
void useArray(int array[], size_t len) { ... }
...
useArray(myArray, 24);
useArray(&myArray[24], 15);
useArray(&myArray[39], 26);
OR
void useArray(int *start, int *end) { ... }
...
useArray(myArray, myArray + 24);
useArray(myArray + 24, myArray + 39);
useArray(myArray + 39, myArray + 65);
The first is more of a C way, the second a more C++ way. Note that with the second way, the range is [start, end) - end isn't included in the range as you see a lot in C++.
EDIT: You edited your post to mention that you're using glTexCoordPointer(). In that case pass the start of the array to glTexCoordPointer(), which will be either myArray, myArray + 24 or myArray + 39.
The size of the array still has to be known though, and is passed to functions such as glDrawArrays or glDrawElements(), which will then start reading from the array. If you were using glDrawArrays(), the length of the array is passed as the second argument. Therefore your code could be something like:
glTexCoordPointer(..., ..., ..., my_array);
...
glDrawArrays(..., 0, 24);
glTexCoordPointer(..., ..., ..., my_array + 24);
...
glDrawArrays(..., 0, 15);
glTexCoordPointer(..., ..., ..., my_array + 39);
...
glDrawArrays(..., 0, 26);
There is no upper bound range checking, so you have to take care of that yourself. But you can pass &my_array[0] to one function, and &my_array[24] to another. Maybe add a len parameter to your function to take care of upper range.
You could refactor your functions to use 'iterators': a pointer to the begin and to the end of the array-range you're interested in:
void somefunction( int* begin, int* end ) {
for( int* i=begin; i != end; ++i ) {
//stuff with *i
}
}
// usage:
somefunction( my_array+0, my_array+23 );
somefunction( my_array+24, my_array+38 );
somefunction( my_array+39, my_array+64 );
Bonus points: if you make your function a template, you can use it with other iterators too:
template<typename T>
void somefunction( T begin, T end ) {
for( T i=begin; i != end; ++i ) {
//stuff with *i
}
}
vector<int> values(100);
somefunction( values.begin(), values.end() );
somefunction( values.rbegin(), values.rend() );
...
I would return or do something like std::pair<pointer_type, pointer_type> which contains {Begin_Pointer, End_Pointer} so, Let's if we need to slice a raw array(in C/C++ land just a pointer) with specific parts/blocks. I would return take something like
pointer_type element_begin = raw_array+begin;
pointer_type element_end = raw_array+end;
std::pair<pointer_type, pointer_type> = std::make_pair(element_begin, element_end);
I will have a convenient function to which I give those begin and end non-negative values and it will return me a std::pair