Sizes of the dimensions of a multidimensional array - c++

I knew it but now can't remember the function template std::??? that returns the sizes used for declaring a multidimensional arrays. Could you remind me this function? It works like in the below example, if I remember it right.
#include <iostream>
int main() {
int a[][2] = {{}, {}, {}};
std::cout << std::size(a) << std::endl; // outputs 3
std::cout << std::???<0>(a) << std::endl; // outputs 3, same as std::size(a)
std::cout << std::???<1>(a) << std::endl; // outputs 2, same as std::size(a[0])
}
I do not need its implementations, I want to use the existing function.
Thank #sklott the answer:
#include <iostream>
#include <type_traits>
int main() {
int a[][2] = {{}, {}, {}};
std::cout << std::size(a) << std::endl; // outputs 3
std::cout << std::extent<decltype(a), 0>::value << std::endl; // outputs 3, same as std::size(a)
std::cout << std::extent<decltype(a), 1>::value << std::endl; // outputs 2, same as std::size(a[0])
}

Thank #sklott the answer:
#include <iostream>
#include <type_traits>
int main() {
int a[][2] = {{}, {}, {}};
std::cout << std::size(a) << std::endl; // outputs 3
std::cout << std::extent<decltype(a), 0>() << std::endl; // outputs 3, same as std::size(a)
std::cout << std::extent<decltype(a), 1>() << std::endl; // outputs 2, same as std::size(a[0])
}

Related

Is it possible to assign to an array from an initializer list?

I am trying to make it possible to assign to an array from an initializer list in C++, if this is possible how to do it? may be the new versions of C++ needs to achieve it or not?
Code:
#include <iostream>
#include <array>
using namespace std;
int main()
{
int arrayName_A[5];
arrayName_A = {1,2,3,4,5};
for (int i=0;i<5;i++)
{
cout << "\n Starting checker" << '\n';
cout << "checked: " << arrayName_A[i] << '\n';
}
}
No, it's not possible. You either have to intialize the array directly:
int arrayName_A[5] = {1,2,3,4,5};
or use std::array instead:
std::array<int, 5> arrayName_A;
arrayName_A = {1, 2, 3, 4, 5};
Arrays do not have the assignment operator. Arrays are non-modifiable lvalues.
That is you may not write for example
int a[3] = { 1, 2, 3 };
int b[3] = a;
or
int a[3] = { 1, 2, 3 };
int b[3];
b = a;
You may set each element of an array with a value from an initializer list using the range-based for loop as it is shown in the demonstrative program below.
#include <iostream>
int main()
{
int arrayName_A[5];
size_t i = 0;
for ( const auto &item : { 1, 2, 3, 4, 5 } ) arrayName_A[i++] = item;
for ( const auto &item : arrayName_A ) std::cout << item << ' ';
std::cout << '\n';
return 0;
}
The program output is
1 2 3 4 5
Otherwise use the standard class std::array that has the assignment operator. For example
#include <iostream>
#include <array>
int main()
{
std::array<int, 5> arrayName_A;
arrayName_A = { 1, 2, 3, 4, 5 };
// or
arrayName_A = { { 1, 2, 3, 4, 5 } };
for ( const auto &item : arrayName_A ) std::cout << item << ' ';
std::cout << '\n';
return 0;
}
The program output is the same as shown above that is
1 2 3 4 5
You need to initialize the array as soon as you declare it, like this :
#include <iostream>
#include <array>
using namespace std;
int main()
{
int arrayName_A[5] = {1,2,3,4,5};
for (int i=0;i<5;i++)
{
cout << "\n Starting checker" << '\n';
cout << "checked: " << arrayName_A[i] << '\n';
cout << "\n Starting checker" << '\n';
cout << "checked: " << arrayName_A[i] << '\n';
cout << "\n Starting checker" << '\n';
cout << "checked: " << arrayName_A[i] << '\n';
cout << "\n Starting checker" << '\n';
cout << "checked: " << arrayName_A[i] << '\n';
cout << "\n Starting checker" << '\n';
cout << "checked: " << arrayName_A[i] << '\n';
}
}

Which operations on what type of classes invalidates an Eigen:Ref?

I came across the following behavior with Eigen::Ref :
#include <iostream>
#include <Eigen/Dense>
int main()
{
Eigen::VectorXf a = Eigen::Vector2f{1,2};
Eigen::Ref<Eigen::VectorXf> ref{a};
std::cout << a.transpose() << "\n"; // prints: 1, 2
std::cout << ref.transpose() << "\n"; // prints: 1, 2
a = Eigen::Vector3f{3,4,5};
std::cout << a.transpose() << "\n"; // prints: 3, 4, 5
std::cout << ref.transpose() << "\n"; // prints: 3, 4
return 0;
}
The invalidation of Eigen references does not seem to be documented as far as I can tell. When does it occur?

Struct Values inside Vector Become Corrupted when Passed by Value

I have the following simple struct:
struct Wire {
int start_x;
int end_x;
int start_y;
int end_y;
Wire(int sx, int ex, int sy, int ey): start_x(sx), end_x(ex), start_y(sy), end_y(ey) {}
};
I also have the following print functions that take a std::vector<Wire> and print out some values from the first item:
These functions are indentical apart from the fact that one takes arguments by value and the other by reference.
void print_first_wire_value(std::vector<Wire> wires){
std::cout << "(" << wires[0].start_x << ", " << wires[0].start_y << ")" << std::endl;
}
void print_first_wire_reference(std::vector<Wire> &wires){
std::cout << "(" << wires[0].start_x << ", " << wires[0].start_y << ")" << std::endl;
}
My main function includes the following code.
It populates a vector with wire objects using another function. It then calls both of the print functions.
std::vector<Wire> wires = input_to_wires(first_line);
std::cout << "By value: " << std::endl;
print_first_wire_value(wires);
std::cout << "By reference: " << std::endl;
print_first_wire_reference(wires);
I know for a fact the first start_x and end_x values are 0 and 0. Both print functions should print these values. But bizarrely I instead get this:
By value:
(-543694264, -543694264)
By reference:
(0, 0)
What on earth is going on here?
Minimum Reproducible Example
(Please excuse the seemingly strange names, this is the start of a solution to a programming challenge from advent of code).
day3_lib.h
#pragma once
#include <vector>
#include <string>
struct Wire{
Wire(int sx, int ex, int sy, int ey);
};
std::vector<Wire> populate_wires();
void print_first_wire_value(std::vector<Wire> wires);
void print_first_wire_reference(std::vector<Wire> &wires);
day3_lib.cpp
#include <vector>
#include <sstream>
#include <iostream>
#include <stdexcept>
struct Wire {
int start_x;
int end_x;
int start_y;
int end_y;
Wire(int sx, int ex, int sy, int ey): start_x(sx), end_x(ex), start_y(sy), end_y(ey) {}
};
std::vector<Wire> populate_wires(){
std::vector<Wire> wires;
Wire wire1(0, 0, 1003, 0);
Wire wire2(1003, 0, 1003, -138);
Wire wire3(1003, 0, 662, -138);
wires.push_back(wire1);
wires.push_back(wire2);
wires.push_back(wire3);
return wires;
}
void print_first_wire_value(std::vector<Wire> wires){
std::cout << "(" << wires[0].start_x << ", " << wires[0].start_y << ")" << std::endl;
}
void print_first_wire_reference(std::vector<Wire> &wires){
std::cout << "(" << wires[0].start_x << ", " << wires[0].start_y << ")" << std::endl;
}
day3.cpp
#include "./day3_lib.h"
#include <fstream>
#include <iostream>
int main(){
std::vector<Wire> wires = populate_wires();
std::cout << "By value: " << std::endl;
print_first_wire_value(wires);
std::cout << "By reference: " << std::endl;
print_first_wire_reference(wires);
}

Shortest solution to permute the elements of a std::vector using stl

Assume that you have an std::vector<T> of some type T and a selection of indices std::vector<int> of this vector. Now I'm looking for a function permute(const std::vector<T>& vector, const std::vector<int>& indices), that returns the permuted vector with respect to the given indices.
The problem is easily solved by writing a short function like depicted below:
template<typename T>
std::vector<T> permute(const std::vector<T>& matrix, const std::vector<int>& indices) {
std::vector<T> ret;
for (auto p : indices) {
ret.push_back(matrix[p]);
}
return ret;
}
int main(int, char**) {
std::vector<int> perm{ 1,2,0 };
std::vector<std::vector<double>> matrix = { {1.,2.,3.},{4.,5.,6.},{7.,8.,9.} };
auto matrixPerm=permute(matrix, perm);
std::cout << matrixPerm[0][0] << " == " << matrix[1][0] << std::endl;
std::cout << matrixPerm[1][0] << " == " << matrix[2][0] << std::endl;
std::cout << matrixPerm[2][0] << " == " << matrix[0][0] << std::endl;
}
I'm now wondering what might be most elegant version of this program, if we can use STL or even the Boost libraries. In STL for example we have shuffle(), but we cannot say in what way to shuffle.
Does anyone now, how to shorten the function?
Solution using std::transform()
#include <vector>
#include <iostream>
#include <iterator>
#include <algorithm>
int main(int, char**) {
std::vector<int> perm{ 1,2,0 };
std::vector<std::vector<double>> matrix = { {1.,2.,3.},{4.,5.,6.},{7.,8.,9.} };
std::vector<std::vector<double>> output;
std::transform(perm.begin(), perm.end(), std::back_inserter(output), [&](int i) { return matrix[i]; });
std::cout << output[0][0] << " == " << matrix[1][0] << std::endl;
std::cout << output[1][0] << " == " << matrix[2][0] << std::endl;
std::cout << output[2][0] << " == " << matrix[0][0] << std::endl;
}
You can transform the indices into iterators and then create an indirect range with Boost.Range.
#include <iostream>
#include <iterator>
#include <algorithm>
#include <boost/range/adaptor/indirected.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/algorithm/copy.hpp>
int main(int, char**) {
using namespace boost::adaptors;
std::vector<int> perm{ 1,2,0 };
std::vector<std::vector<double>> matrix = { {1.,2.,3.},{4.,5.,6.},{7.,8.,9.} };
std::vector<std::vector<double>> output;
auto permutation = perm | transformed( [&matrix](int x) { return matrix.begin() + x; }) | indirected;
boost::copy(
permutation,
std::back_inserter(output));
std::cout << output[0][0] << " == " << matrix[1][0] << std::endl;
std::cout << output[1][0] << " == " << matrix[2][0] << std::endl;
std::cout << output[2][0] << " == " << matrix[0][0] << std::endl;
}
You could skip copying the elements and just process the range if you don't need a real vector.
The range adaptor uses the permutation iterator from the Boost.Iterator library. You can also use this directly, but you have to manually define begin and end:
auto begin = make_permutation_iterator( matrix.begin(), perm.begin() );
auto end = make_permutation_iterator( matrix.end(), perm.end() );
std::copy(begin, end, std::back_inserter(output) );

Eigen Increment Column by One

How to increment a column of a dynamic matrix by one, as an in place operation (without creating copies/intermediates) ?
Attempt:
#include <Eigen/Dense>
#include <iostream>
#include <stdint.h>
int main(void){
Eigen::MatrixXf A;
A = Eigen::MatrixXf::Random(3, 5);
std::cout << A << std::endl << std::endl;
A.col(1) = A.col(1)*2; //this works.
A.col(1) = A.col(1) + 1; //this doesn't work.
std::cout << A << std::endl;
}
I found a way to do this. But I don't know if the operation is in place.
This is similar to eigen: Subtracting a scalar from a vector
#include <Eigen/Dense>
#include <iostream>
int main(void){
Eigen::MatrixXf A;
A = Eigen::MatrixXf::Random(3, 5);
std::cout << A << std::endl << std::endl;
A.col(1) = A.col(1)*2;
A.col(1) = A.col(1) + Eigen::VectorXf::Ones(3);
std::cout << A << std::endl;
}
Another way is to use array operation. This way seem better (I guess).
https://eigen.tuxfamily.org/dox/group__TutorialArrayClass.html
#include <Eigen/Dense>
#include <iostream>
int main(void){
Eigen::MatrixXf A;
A = Eigen::MatrixXf::Random(3, 5);
std::cout << A << std::endl << std::endl;
A.array() += 1;
A.col(1).array() += 100;
std::cout << A << std::endl;
}