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.
Related
This is question is out of curiosity, not necessity. One way I have found C++11's range based for loop useful is for iterating over discrete objects:
#include <iostream>
#include <functional>
int main()
{
int a = 1;
int b = 2;
int c = 3;
// handy:
for (const int& n : {a, b, c}) {
std::cout << n << '\n';
}
I would like to be able to use the same loop style to modify non-const references too, but I believe it is not allowed by the standard (see Why are arrays of references illegal?):
// would be handy but not allowed:
// for (int& n : {a, b, c}) {
// n = 0;
// }
I thought of two workarounds but these seem like they could incur some minor additional cost and they just don't look as clean:
// meh:
for (int* n : {&a, &b, &c}) {
*n = 0;
}
// meh:
using intRef = std::reference_wrapper<int>;
for (int& n : {intRef (a), intRef (b), intRef (c)}) {
n = 0;
}
}
So the question is, is there a cleaner or better way? There may be no answer to this but I'm always impressed with the clever ideas people have on stackoverflow so I thought I would ask.
Picking up #Sombrero Chicken's idea, here is an approach with less typing:
template <class ...Args> constexpr auto ref(Args&&... args)
{
using First = std::tuple_element_t<0, std::tuple<Args...>>;
using WrappedFirst = std::reference_wrapper<std::remove_reference_t<First>>;
constexpr auto n = sizeof...(Args);
return std::array<WrappedFirst, n>{std::ref(args)...};
}
which can be used via
for (int& n : ref(a, b, c))
n = 0;
Instead of constructing a reference_wrapper yourself you could use std::ref, that's as far as you can get:
using std::ref;
for (int& n : {ref(a), ref(b), ref(c)}) {
n = 0;
}
I noticed while doing some F# experiments that if write my own reduce function for Array that it performs much better than the built in reduce. For example:
type Array with
static member inline fastReduce f (values : 'T[]) =
let mutable result = Unchecked.defaultof<'T>
for i in 0 .. values.Length-1 do
result <- f result values.[i]
result
This seems to behave identically to the built in Array.reduce but is ~2x faster for simple f
Is the built in one more flexible in some way?
By looking at the generated IL code it's easier to understand what's happening.
Using the built-in Array.reduce:
let reducer (vs : int []) : int = Array.reduce (+) vs
Gives the following equivalent C# (reverse engineered from the IL code using ILSpy)
public static int reducer(int[] vs)
{
return ArrayModule.Reduce<int>(new Program.BuiltIn.reducer#31(), vs);
}
Array.reduce looks like this:
public static T Reduce<T>(FSharpFunc<T, FSharpFunc<T, T>> reduction, T[] array)
{
if (array == null)
{
throw new ArgumentNullException("array");
}
int num = array.Length;
if (num == 0)
{
throw new ArgumentException(LanguagePrimitives.ErrorStrings.InputArrayEmptyString, "array");
}
OptimizedClosures.FSharpFunc<T, T, T> fSharpFunc = OptimizedClosures.FSharpFunc<T, T, T>.Adapt(reduction);
T t = array[0];
int num2 = 1;
int num3 = num - 1;
if (num3 >= num2)
{
do
{
t = fSharpFunc.Invoke(t, array[num2]);
num2++;
}
while (num2 != num3 + 1);
}
return t;
}
Notice that it invoking the reducer function f is a virtual call which typically the JIT:er struggles to inline.
Compare to your fastReduce function:
let reducer (vs : int []) : int = Array.fastReduce (+) vs
The reverse-engineered C# code:
public static int reducer(int[] vs)
{
int num = 0;
for (int i = 0; i < vs.Length; i++)
{
num += vs[i];
}
return num;
}
A lot more efficient as the virtual call is now gone. It seems that in this case F# inlines both the code for fastReduce as well as (+).
There's some kind of cut-off in F# as more complex reducer functions won't be inlined. I am unsure on the exact details.
Hope this helps
A side-note; Unchecked.defaultOf returns null values for class types in .NET such as string. I prefer LanguagePrimitives.GenericZero.
PS. A common trick for the real performance hungry is to loop towards 0. In F# that doesn't work for for-expressions because of a slight performance bug in how for-expressions are generated. In those case you can try to implement the loop using tail-recursion.
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.
Is it possible to use the foreach syntax of C++11 with Eigen matrices? For instance, if I wanted to compute the sum of a matrix (I know there's a builtin function for this, I just wanted a simple example) I'd like to do something like
Matrix2d a;
a << 1, 2,
3, 4;
double sum = 0.0;
for(double d : a) {
sum += d;
}
However Eigen doesn't seem to allow it. Is there a more natural way to do a foreach loop over elements of an Eigen matrix?
Range-based for loops need the methods .begin() and .end() to be implemented on that type, which they are not for Eigen matrices. However, as a pointer is also a valid random access iterator in C++, the methods .data() and .data() + .size() can be used for the begin and end functions for any of the STL algorithms.
For your particular case, it's more useful to obtain start and end iterators yourself, and pass both iterators to a standard algorithm:
auto const sum = std::accumulate(a.data(), a.data()+a.size(), 0.0);
If you have another function that really needs range-based for, you need to provide implementations of begin() and end() in the same namespace as the type (for argument-dependent lookup). I'll use C++14 here, to save typing:
namespace Eigen
{
auto begin(Matrix2d& m) { return m.data(); }
auto end(Matrix2d& m) { return m.data()+m.size(); }
auto begin(Matrix2d const& m) { return m.data(); }
auto end(Matrix2d const& m) { return m.data()+m.size(); }
}
STL style iterator support has been added to Eigen in version 3.4.
See https://eigen.tuxfamily.org/dox-devel/group__TutorialSTL.html
For OP's question, you can do the following:
Matrix2d A;
A << 1, 2,
3, 4;
double sum = 0.0;
for(auto x : A.reshaped())
sum += x;
A pointer to the data array of the matrix can be obtained using the member function .data().
The size of the data array can also be obtained using the member function .size().
Using these two, we now have the pointers to the first element and end of the array as a.data() and a.data()+a.size().
Also, we know that an std::vector can be initialized using iterators (or array pointers in our case).
Thus, we can obtain a vector of doubles that wraps the matrix elements with std::vector<double>(a.data(), a.data()+a.size()).
This vector can be used with the range-based for loop syntax that is included in your code snippet as:
Matrix2d a;
a << 1, 2,
3, 4;
double sum = 0.0;
for(double d : std::vector<double>(a.data(), a.data()+a.size())) {
sum += d;
}
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.