I'm doing a problem where I need to create a stack of n-dimensional coordinates. I have implemented the coordinates as type std::array<std::size_t, n_dims>, where n_dims is a compile-time constant.
Q: What is the best way to push a coordinate to the stack?
Possibilities:
Creating the array as a variable, then pushing it to the stack. This seems wasteful. A bit less bad if I use move semantics:
std::array<std::size_t, 2> my_array = {1, 3};
my_stack.push(std::move(my_array));
// or my_stack.emplace(...)
but still unnecessarily complicated.
Using std::stack::emplace. This doesn't seem to work. I think it's because std::array is an aggregate type. (I'd like to understand this point better -- I believe one important consequence is that aggregate types have only default and copy constructors.)
#include <array>
#include <stack>
int main()
{
std::stack<std::array<int, 2>> st;
st.emplace(1,3); // doesn't work
st.emplace({1,3}); // doesn't work
st.emplace({{1,3}}); // doesn't work
}
What should I do?
You can use std::experimental::make_array
#include <experimental/array>
#include <array>
#include <stack>
int main()
{
std::stack<std::array<int, 2>> st;
st.emplace(std::experimental::make_array(1,3));
}
Related
Is this the only solution when there is a pointer that points to a vector and we would like to use accumulate to sum up numbers?
Is there any simpler solution rather than writing a lambda function and using a four argument type of accumulating?
Also, for using std::sort, will the situation be the same?
Here is the code:
#include <random>
#include <vector>
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
int main() {
const int N=3;
auto p=make_unique<array<int,N>> ();
(*p)[0]=3;
(*p)[1]=4;
(*p)[2]=5;
sum=accumulate(p,?,0);
return 0;
}
To answer your immediate question:
std::accumulate(p->begin(), p->end(), 0);
The same syntax will work for other STL algorithms as well.
Other improvements to your code snippet:
Avoid using #include<bits/stdc++.h>, see this post. Similarly for using namespace std, it's considered bad practise.
const N=3 -> const auto N=3
std::array is not a vector and you can initialise it directly using initializer-list syntax:
const auto* obj = new std::array<int,3>{3,4,5};
I want to create a vector which stores name of data types(int,char,bool,etc)
I am looking for something like:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main(int argc,char** argv)
{
vector<typenames> v = {int,float,double,bool};
}
If you have a finite set of types you want to store, you can use <variant>, e.g.
#include <variant>
using VarType = std::variant<int, float, double, bool>;
std::vector<VarType> v;
v.push_back(42);
assert(std::holds_alternative<int>(v.front()));
assert(std::get<int>(v.front()) == 42);
v[0] = true;
assert(std::holds_alternative<bool>(v.front()));
assert(std::get<bool>(v.front()));
Note that if C++17 is not available, you can go with Boost variant.
No. It's not possible. C++ is a statically-typed language, not a dynamic-typed language. What you can do is have set of enums, for types and put them into vector.
enum Type
{
IntType, FloatType, DoubleType, BoolType
};
vector<Type> v;
Or you can use std::variant (C++17).
Your question wasn't clear. Maybe you need std::pair or std::tuple to keep different items (with a defined number of elements).
the following codes pushed back an std::array to a std::vector N times. Is there a more elegant and shorter way of doing this?
#include <iostream>
#include <vector>
#include <array>
#include <iomanip>
#include <complex>
#include <cmath>
int main () {
int N=10;
std::vector< std::array<std::complex<double>,3> > v;
v.reserve(N);
for(int i=0;i<N;i++){
std::array<std::complex<double>,3> el { {0.0,3.0,0.0} };
v.push_back(el);
}
}
Yes but you have to use parentheses when constructing vector
std::vector< std::array<std::complex<double>,3> > v(n, {0.0,3.0,0.0});
If braces are used than initialization list is preferred and in this case you could have unexpected errors.
You can use the std::vector::insert (#3 in the overload set) member function:
int N=10;
std::vector< std::array<std::complex<double>,3> > v;
v.reserve(N);
v.insert(v.end(), N, { {0.0,3.0,0.0} });
Note that #MarekR's answer is preferable for initializing the vector, as it circumvents the call to reserve, and setting up an object during initialization is usually better than subsequent member function calls. The above call to std::vector::insert instead is suitable for adding additional elements later on.
Is there any std container which would be fixed size like std::array, but the size would not be compile time, but runtime?
I want to pass a part of some data I have stored in std::array to std::acculumate and similar functions. I do not want to use std::vector (working on embedded platform), therefore I am looking for something in between.
Assume code like this, what I want is something to be used in place of array_part:
#include <array>
#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>
int main()
{
std::array<float,100> someData;
// fill the data
int dataCount = 50;
std::array_part<float> partOfData(someData.data(),dataCount)); // <<<<< here
const auto s_x = std::accumulate(partOfData.begin(), partOfData.end(), 0.0);
}
If there is no such container, how can I wrap the raw data I have and present them to std::accumulate and other std algorithms?
std::accumulate takes iterators. You can pass it iterators that contain the range of interest:
auto start = partOfData.begin() + 42;
auto end = partOfData.begin() + 77;
const auto s_x = std::accumulate(start, end, 0.0);
Alternatively, you can roll out your own non-owning container-like object. See this question for an example.
It seems to me that I should be able to use std::begin() and std::end() to convert ArrayXd to std::vector<double>; however, when I tried it in the following code, my attempt failed. My understanding is that .data() method on any Eigen object returns a pointer to a continuous block of memory similar to c style array. Therefore, since I can use std::begin(), std::end() on a c style array, I expected that to work with .data() as well. However, Eigen classes are templated, and I think this is what causes me problems, but don't see a way to fix this. How should this be done?
#include <iostream>
#include <vector>
#include <Eigen/Dense>
using namespace Eigen;
int main()
{
ArrayXd e_array(5);
e_array << 3,4,5,6,7;
double c_array[] = {1,2,3,4,5};
//Fails
// std::vector<double> my_vec(std::begin(e_array.data()), std::end(e_array.data()));
// Works
// std::vector<double> my_vec(e_array.data(), e_array.data() + 5);
// Works
// std::vector<double> my_vec(std::begin(c_array), std::end(c_array));
// Works
// std::vector<double> my_vec(c_array, c_array + 5);
return 0;
}
My error message(First lines, the whole message is long):
error: no matching function for call to
‘begin(Eigen::PlainObjectBase >::Scalar*)’
std::vector my_vec(std::begin(e_array.data()),
std::end(e_array.data()))
std::begin(vec.data()) cannot work because data() returns a raw pointer which cannot convey the number of elements in the vector. This version is the best one of yours:
std::vector<double> my_vec(e_array.data(), e_array.data() + 5);
And slightly better:
std::vector<double> my_vec(e_array.data(), e_array.data() + e_array.size());
And you may also be able to do this with many containers, but not with Eigen's ArrayXd in particular, because it lacks begin() and end() (related: http://eigen.tuxfamily.org/bz/show_bug.cgi?id=231).
std::vector<double> my_vec(foo.begin(), foo.end());