remove element from boost::numeric::ublas::vector - boost

If I declare a boost::numeric::ublas::vector aaa and later call the method aaa.erase_element(n), I get a vector with the same size, but with the n-element equal to zero.
Do you know how can I completely remove the element in order to get a lower-size vector?
I can't use std::vector unfortunately...

template<class T> void remove(vector<T> &v, uint idx)
{
assert(idx < v.size());
for (uint i = idx; i < v.size() - 1; i++) {
v[i] = v[i + 1];
}
v.resize(v.size() - 1);
}
Note: this works if T is a primitive type (int, double, etc.) or simple struct. If T is a pointer
type, or contains pointers, then you may need to look after destruction of referenced objects. Or perhaps use ptr_vector.

Related

How to return multiple values (vector and one int value) through function

I am finding connected components of a graph.
Condition : Those components should not be printed in same function, but they should be printed in calling function ( i.e. int main() )
I have gone through the link but got some error.
Returning multiple values from a C++ function
tuple <vector<int>&, int > connected( vector<int>& store, ...)
{
int component_size = 0;
// code
return make_tuple ( store, component_size);
}
int main()
{
// code
for( int i = 0 ; i < V; i++ )
{
if( !visited[i])
{
tie( ans, compo_size ) = connected(edges,
visited, myQ, store, V, i);
for(int i = 0 ; i < compo_size; i++ )
{
cout<< ans[i] <<" ";
}
}
}
}
There are few errors :
error: could not convert 'std::make_tuple(_Elements&& ...) [with _Elements = {std::vector >&, int&}](component_size)' from 'std::tuple >, int>' to 'std::tuple >&, int>'
return make_tuple ( store, component_size);
^
error: invalid initialization of reference of type 'std::vector&' from expression of type 'std::vector'
tie( ans, compo_size ) = connected(edges, visited, myQ, store, V, i);
How to return multiple values (vector and one int value) through function
A function can have at most one return value.
Returning more objects can be emulated by either
modifying one or more objects that are global or are referenced by arguments through indirection or by
returning an object of class type that has multiple sub objects.
You've attempted the latter approach through the use of tuple class template. The reason it doesn't work is explained in the documentation:
template< class... Types >
tuple<VTypes...> make_tuple( Types&&... args );
For each Ti in Types..., the corresponding type Vi in VTypes... is std::decay<Ti>::type unless application of std::decay results in std::reference_wrapper<X> for some type X, in which case the deduced type is X&.
As such, your invocation of make_tuple is deduced to return tuple <vector<int>, int > which is wrong because the function is supposed to return tuple <vector<int>&, int > instead. This can be fixed using std::ref so that the correct type is deduced:
std::make_tuple(std::ref(store), component_size);
As eerorika mentioned, you could use std::ref() as follow:
std::tuple <std::vector<int>&, int > connected( std::vector<int>& store, ...)
{
int component_size = 0;
// code
return std::make_tuple ( std::ref(store), component_size);
}
However, there is really no point in returning a reference to the input vector since it is already a non-const reference on input. So changing the vector in place is going to be enough. On return you get a modified version. However, that's probably not what you are looking to do (i.e. you probably wanted to make a copy of store and return the copy with the other arrays appended...)
That also means you're going to have yet another copy when you create the tuple:
std::tuple <std::vector<int>, int > connected( std::vector<int>& store, ...)
{
int component_size = 0;
std::vector<int> result;
// or maybe a straight copy, depends on your needs in "code"
//std::vector<int> result(store);
// code
return std::make_tuple ( result, component_size);
}
As mentioned by others, having a result in the list of arguments is probably your best bet:
int connected( std::vector<int> & result, std::vector<int> const & store, ...)
{
int component_size = 0;
// code
return component_size;
}
Also, wouldn't component_size == result.size() be true? If so, you should not return anything because it's going to be more confusing.
That simplifies the function to this point:
void connected( std::vector<int> & result, std::vector<int> const & store, ...)
{
// code
}

Function taking std::initializer_list

I came across a function a colleague had written that accepted an initializer list of std::vectors. I have simplified the code for demonstration:
int sum(const std::initializer_list<std::vector<int>> list)
{
int tot = 0;
for (auto &v : list)
{
tot += v.size();
}
return tot;
}
Such a function would allow you call the function like this with the curly braces for the initializer list:
std::vector<int> v1(50, 1);
std::vector<int> v2(75, 2);
int sum1 = sum({ v1, v2 });
That looks neat but doesn't this involve copying the vectors to create the initializer list? Wouldn't it be more efficient to have a function that takes a vector or vectors? That would involve less copying since you can move the vectors. Something like this:
int sum(const std::vector<std::vector<int>> &list)
{
int tot = 0;
for (auto &v : list)
{
tot += v.size();
}
return tot;
}
std::vector<std::vector<int>> vlist;
vlist.reserve(2);
vlist.push_back(std::move(v1));
vlist.push_back(std::move(v2));
int tot = sum2(vlist);
Passing by initializer list could be useful for scalar types like int and float, but I think it should be avoided for types like std::vector to avoid unnecessary copying. Best to use std::initializer_list for constructors as it intended?
That looks neat but doesn't this involve copying the vectors to create the initializer list?
Yes, that is correct.
Wouldn't it be more efficient to have a function that takes a vector or vectors?
If you are willing to move the contents of v1 and v2 to a std::vector<std::vector<int>>, you could do the samething when using std::initializer_list too.
std::vector<int> v1(50, 1);
std::vector<int> v2(75, 2);
int sum1 = sum({ std::move(v1), std::move(v2) });
In other words, you can use either approach to get the same effect.

Can I convert a non-const function argument to const and set the size of array?

Arrays require a constant to initialize the size. Hence, int iarr[10]
I thought I could possibly take a non-const argument and convert it to const then use it for an array size
int run(int const& size);
int run(int const& size)
{
const int csize = size;
constexpr int cesize = csize;
std::array<int, cesize> arr;
}
This, unfortunately doesn't work and I thought of using const_cast as
int run(int& size);
int run(int& size)
{
const int val = const_cast<int&>(size);
constexpr int cesize = val;
std::array<int, cesize> arr;
}
and this won't work either. I've read through a few SO posts to see if I can find anything
cannot-convert-argument-from-int-to-const-int
c-function-pass-non-const-argument-to-const-reference-parameter
what-does-a-const-cast-do-differently
Is there a way to ensure the argument is const when used as an initializer for the size of an array?
EDIT: I'm not asking why I can't initialize an array with a non-const. I'm asking how to initialize an array from a non-const function argument. Hence, initialize-array-size-from-another-array-value is not the question I am asking. I already know I can't do this but there may be a way and answer has been provided below.
std::array is a non-resizable container whose size is known at compile-time.
If you know your size values at compile-time, you can pass the value as a non-type template argument:
template <int Size>
int run()
{
std::array<int, Size> arr;
}
It can be used as follows:
run<5>();
Note that Size needs to be a constant expression.
If you do not know your sizes at compile-time, use std::vector instead of std::array:
int run(int size)
{
std::vector<int> arr;
arr.resize(size); // or `reserve`, depending on your needs
}
std::vector is a contiguous container that can be resized at run-time.
I'm asking how to initialize an array from a non-const function argument.
As you saw, it is not possible initialize an array size with an variable, because you need to specify the size or array at compiler time.
To solve your problem you should use std::vector that works like an array but you can resize it at run time. You can handle de vector as if you were handled an array, using the operator [], for example:
class MyClass
{
vector<char> myVector;
public:
MyClass();
void resizeMyArray(int newSize);
char getCharAt(int index);
};
MyClass::MyClass():
myVector(0) //initialize the vector to elements
{
}
void MyClass::resizeMyArray(int newSize)
{
myVector.clear();
myVector.resize(newSize, 0x00);
}
char MyClass::getCharAt(int index)
{
return myVector[index];
}
For more information check this link: http://www.cplusplus.com/reference/vector/vector/
Upgrade: Also, considere that std::array can't be resize, as this links say:
Arrays are fixed-size sequence containers: they hold a specific number of elements ordered in a strict linear sequence.

flatten vectors in a map

In C++, I have a map < int, vector < double > > or map < int, vector < some_Struct > >, I need to concatenate the vectors in this map and return the result.
The first version of the function is below:
#include <algorithm>
#include <vector>
vector < double >
flattenRecords(const map < int, vector < double > > & selected, int num_kept_reps)
{
vector < double > records;
int cnt = 0;
for (auto it = selected.begin(); it != selected.end(); ++it) {
records.insert(records.end(),
make_move_iterator(it->second.begin()),
make_move_iterator(it->second.end()));
cnt += 1;
if (cnt >= num_kept_reps)
break;
}
return records;
}
I know this is not what I intended to do, because I would like to keep the data in the map, and thus should not use make_move_iterator.
The codes can compile using g++ (GCC) 4.4.7 with the -std=c++0x flag.
So here is the question, I declare the map to be const, what happens when I try to use something like std::move to the vector in the map?
My second version is to use:
copy(it->second.begin(), it->second.end(), back_inserter(records));
I guess this does what I intend to do.
I am quite new to C++. The STL gives me a feeling of coding in python so I would like to try it.
Instead of using make_move_iterator(Iterator), just use Iterator if you would not like to move the elements. Eg:
records.insert(records.end(), it->second.begin(), it->second.end());
Your second version, as you guess, does indeed what you try to achieve.
Regarding your question about std::move on a const map, the std::move won't do anything in such a case. Since std::move is unconditional cast to rvalue, it'll cast the element to a const reference to an rvalue. Because it's const it'll match the lvalue ctor (copy ctor in this case), and not the move (copy) ctor.
Eg:
const std::string s1 = "Test";
const std::string s2 = std::move(s1);
This will invoke the copy constructor of std::string, not the move constructor. Hence, it'll do a copy, not a move.
This will do a move:
std::string s1 = "Test";
const std::string s2 = std::move(s1);
The s2 parameter in both examples does not have to be const. It makes no difference regarding the copy/move.
There is a 'pythonic' alternative, which you may like if you come from Python, using lambda and a "mapped-reduce" function
std::vector<double> merged = std::accumulate(selected.begin(),
selected.end(),
std::vector<double>(),
[](const std::vector<double>& a, std::vector<double>& b)
{
std::vector<double> result(a);
std::copy(b.begin(), b.end(), std::back_inserter(result));
return result;
});
);
std::move does not actually move data. It casts a reference to a r-value reference, which, if non-const, is a "movable" data type that move constructors can use. But it will never remove a const type qualifier, so using std::move on a const reference will not cast it to a movable type.

instantiate pair object in C++

I have a vertex class with many objects, e.g.
class Vertex{
int i;
public:
Vertex(const int & a):i(a){}
};
Vertex v1(1),v2(2)...v100(100);
Now I want to make 50 pairs, each pair linking two vertices. What is the best way to achieve this? I definitely don't want to do the following:
std::pair<const Vertex &, const Vertex &> p1(v1,v2);
...
std::pair<const Vertex &, const Vertex &> p50(v99,v100);
std::make_pair seems to be a better choice. But it only accept values, not references, if I understand correctly. Thanks a lot.
std::make_pair can be used to create pairs of references through the use of std::ref. std::ref stores a reference in a std::reference_wrapper, which through template type deduction, reduces back to the reference. For a const reference, use std::cref.
As the other answers suggest, I'd recommend storing your Vertexes in a std::vector, and initialize them in a for loop. Similarly, store your std::pairs of Vertex references in a vector and construct them in a loop as well.
constexpr auto num_vertices = 100;
std::vector<Vertex> v;
v.reserve(num_vertices);
for (auto i = 0; i < num_vertices; ++i)
v.emplace_back(i);
std::vector<std::pair<const Vertex&, const Vertex&>> p;
p.reserve(num_vertices/2);
for (auto i = 0; i < num_vertices; i += 2)
p.emplace_back(v[i], v[i+1]);
Notice that emplace_back is used to construct the Vertexes and std::pairs in-place.
However, if you are tied to 50 lines of pair initialization, and want to use the type deduction offered by std::make_pair, use:
auto p1 = std::make_pair(std::cref(v1), std::cref(v2)),
p2 = std::make_pair(std::cref(v3), std::cref(v4)),
// ...
p50 = std::make_pair(std::cref(v99), std::cref(v100));
But in this case, it's simpler to just use uniform initialization:
std::pair<const Vertex&, const Vertex&> p1 = {v1, v2},
p2 = {v2, v3},
// ...
p50 = {v99, v100};
Here's a live example on ideone.com.
Why not use a std::vector to store your pairs of Vertex's?
std::vector<std::pair<Vertex, Vertex>> v;
v.reserve(50); // Reserve memory to avoid unnecessary allocations.
for (int i = 1; i < 100; i += 2) {
v.emplace_back(i, i + 1); // Create 50 pairs in vector.
}
Later access individual vertices like so:
auto& p1 = v[0];
/* ... */
auto& p50 = v[49];
If you really want to keep 100 variables for all the vertices then you can store constant references to Vertex in std::pair using std::reference_wrapper:
auto p1 = std::make_pair(std::cref(v1), std::cref(v2));

Resources