Pass v.cwiseAbs() to a function that accept Ref<VectorXd> - eigen

The following does not seem to work.
void Foo(Ref<VectorXd> v) {
// modifies v
}
Eigen::VectorXd v;
Foo(v.cwiseAbs());
With the following error message
error: could not convert 'Eigen::ArrayBase::cwiseAbs() const with Derived = Eigen::ArrayWrapper, -1, 1, true>, -1, 1, false> >; Eigen::ArrayBase::CwiseAbsReturnType = Eigen::CwiseUnaryOp, const Eigen::ArrayWrapper, -1, 1, true>, -1, 1, false> > >; typename Eigen::internal::traits::Scalar = double' from 'const CwiseAbsReturnType {aka const Eigen::CwiseUnaryOp, const Eigen::ArrayWrapper, -1, 1, true>, -1, 1, false> > >}' to 'Eigen::Ref >'
Any suggestions why and how to fix?

This doesn't work, because two additional const qualifiers are required in order to mach the expression returned by .cwiseAbs(). This makes sense, because it should not be possible to modify the result of v.cwiseAbs() by a function that accepts this argument in the form of a reference. The following code compiles:
void Foo(const Ref<const VectorXd>& v) {
std::cout << v << std::endl;
}
int main() {
Eigen::VectorXd v(3);
v << 1,-2,3;
Foo(v.cwiseAbs());
}
With this modification, however, it is not allowed to modify v within Foo().
The simplest solution is probably to drop Ref<> and to use
Foo(VectorXd v) {...}
instead. This generates a local copy, but this should not be an issue in terms of performance, moreover since it is anyhow impossible to avoid any copy if v is to be modified within Foo(). If Ref is kept in the signature of Foo, one can make a copy of v.cwiseAbs() and call Foo() with that copy:
void Foo(Ref<VectorXd> v) {...}
...
Eigen::VectorXd w = v.cwiseAbs();
Foo(w);
As suggested by #chtz, an alternative that is available with C++11 is
void Foo(VectorXd&& v) {...}
While this allows to modify v within Foo(), it can be somewhat dangerous to use because only a temporary is changed in Foo(). Modifications of v done in Foo() will not change v in main().

Related

Create function with unknown number of std::array [duplicate]

This question already has answers here:
Concatenating a sequence of std::arrays
(9 answers)
Closed 3 years ago.
I am trying to make a function that pass that test:
TEST(MyCat, CheckOn2Arrays){
std::array<float, 3> vec1{1.0f, 2.0f, 3.0f};
std::array<float, 3> vec2{4.0f, 5.0f, 6.0f};
std::array<float, 6> r = MyCat(vec1, vec2);
EXPECT_EQ(r[0], 1.0f);
EXPECT_EQ(r[1], 2.0f);
EXPECT_EQ(r[2], 3.0f);
EXPECT_EQ(r[3], 4.0f);
EXPECT_EQ(r[4], 5.0f);
EXPECT_EQ(r[5], 6.0f);
}
I have writen that function:
template<class T, size_t N>
auto MyCat((std::array<T, N>) ... arrays) ->
decltype(std::array<T, N*sizeof...(arrays)>) {
std::array<T, sizeof...(arrays)*N> retArray;
int i = 0;
for(std::array<T, N> array: arrays){
T* = array.begin();
while(!T){
retArray[i] = &T;
i++;
T++;
}
}
return retArray;
}
The function must take an arbitrary number of arguments and return an object of type std::array. All arguments are of type std::array (T and N are the same for all function arguments).
Im getting that errors and cant understand how to solve them..
../src/test/../myproject/MyCat.h:4:29: error: expected primary-expression before ‘)’ token
auto MyCat((std::array<T, N>) ... arrays) ->
^
../src/test/../myproject/MyCat.h:4:6: warning: variable templates only available with
std=c++14 or -std=gnu++14
auto MyCat((std::array<T, N>) ... arrays) ->
^
../src/test/../myproject/MyCat.h:4:43: error: expected ‘;’ before ‘->’ token
auto MyCat((std::array<T, N>) ... arrays) ->
^
../src/test/MyCat_test.cc: In member function ‘virtual void
MyCat_CheckOn2Arrays_Test::TestBody()’:
../src/test/MyCat_test.cc:10:35: error: missing template arguments before ‘(’ token
std::array<float, 6> r = MyCat(vec1, vec2);
Here is a C++17 way to do it, but I don't consider it pretty:
template<class T, std::size_t ... N>
auto MyCat(std::array<T, N> ... arrays)
{
constexpr std::size_t NSum = (N + ...);
std::array<T, NSum> retArray;
auto outIt = retArray.begin();
((outIt = std::copy(arrays.begin(), arrays.end(), outIt)), ...);
return retArray;
}
https://godbolt.org/z/ha9NSY
This function takes any number of std::arrays with the same type but potentially different sizes. (You could disallow different sizes if you wanted, left as exercise to the reader.)
We compute the total size (by summing all N in a fold expression) at compile-time (constexpr) and then create a return array of that size.
Next, the ugly part: We want to perform some operation for every variadic argument, so we use a fold expression on the comma operator. We want to copy the current variadic argument (arrays) to the correct section of retArray. Thankfully, std::copy returns an updated iterator for the output, so we can use that to keep track of where to copy to. Note that you need parenthesis around both the comma-operated expression (the iterator assignment) and around the whole fold expression.
It works, but again, not pretty. And it's not even constexpr (because std::copy is not constexpr)...

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
}

Variadic Template Recursion

I am trying to use recursion to solve this problem where if i call
decimal<0,0,1>();
i should get the decimal number (4 in this case).
I am trying to use recursion with variadic templates but cannot get it to work.
Here's my code;
template<>
int decimal(){
return 0;
}
template<bool a,bool...pack>
int decimal(){
cout<<a<<"called"<<endl;
return a*2 + decimal<pack...>();
};
int main(int argc, char *argv[]){
cout<<decimal<0,0,1>()<<endl;
return 0;
}
What would be the best way to solve this?
template<typename = void>
int decimal(){
return 0;
}
template<bool a,bool...pack>
int decimal(){
cout<<a<<"called"<<endl;
return a + 2*decimal<pack...>();
};
The problem was with the recursive case, where it expects to be able to call decltype<>(). That is what I have defined in the first overload above. You can essentially ignore the typename=void, the is just necessary to allow the first one to compile.
A possible solution can be the use of a constexpr function (so you can use it's values it's value run-time, when appropriate) where the values are argument of the function.
Something like
#include <iostream>
constexpr int decimal ()
{ return 0; }
template <typename T, typename ... packT>
constexpr int decimal (T const & a, packT ... pack)
{ return a*2 + decimal(pack...); }
int main(int argc, char *argv[])
{
constexpr int val { decimal(0, 0, 1) };
static_assert( val == 2, "!");
std::cout << val << std::endl;
return 0;
}
But I obtain 2, not 4.
Are you sure that your code should return 4?
-- EDIT --
As pointed by aschepler, my example decimal() template function return "eturns twice the sum of its arguments, which is not" what do you want.
Well, with 0, 1, true and false you obtain the same; with other number, you obtain different results.
But you can modify decimal() as follows
template <typename ... packT>
constexpr int decimal (bool a, packT ... pack)
{ return a*2 + decimal(pack...); }
to avoid this problem.
This is a C++14 solution. It is mostly C++11, except for std::integral_sequence nad std::index_sequence, both of which are relatively easy to implement in C++11.
template<bool...bs>
using bools = std::integer_sequence<bool, bs...>;
template<std::uint64_t x>
using uint64 = std::integral_constant< std::uint64_t, x >;
template<std::size_t N>
constexpr uint64< ((std::uint64_t)1) << (std::uint64_t)N > bit{};
template<std::uint64_t... xs>
struct or_bits : uint64<0> {};
template<std::int64_t x0, std::int64_t... xs>
struct or_bits<x0, xs...> : uint64<x0 | or_bits<xs...>{} > {};
template<bool...bs, std::size_t...Is>
constexpr
uint64<
or_bits<
uint64<
bs?bit<Is>:std::uint64_t(0)
>{}...
>{}
>
from_binary( bools<bs...> bits, std::index_sequence<Is...> ) {
(void)bits; // suppress warning
return {};
}
template<bool...bs>
constexpr
auto from_binary( bools<bs...> bits={} )
-> decltype( from_binary( bits, std::make_index_sequence<sizeof...(bs)>{} ) )
{ return {}; }
It generates the resulting value as a type with a constexpr conversion to scalar. This is slightly more powerful than a constexpr function in its "compile-time-ness".
It assumes that the first bit is the most significant bit in the list.
You can use from_binary<1,0,1>() or from_binary( bools<1,0,1>{} ).
Live example.
This particular style of type-based programming results in code that does all of its work in its signature. The bodies consist of return {};.

remove_if on a map trying to pass a const as a non-const - why?

Here's a bit of code which is supposed to filter out the elements of a map which satisfy a predicate, into a new map (MCVE-fied):
#include <algorithm>
#include <unordered_map>
#include <iostream>
using namespace std;
int main() {
unordered_map<string, int> m = { { "hello", 1 }, { "world", 2 } };
auto p = [](const decltype(m)::value_type& e) { return e.second == 2; };
const auto& m2(m);
auto m3(m2);
auto it = remove_if(m3.begin(), m3.end(), p);
m3.erase(it, m3.end());
cout << "m3.size() = " << m3.size() << endl;
return 0;
}
Compilation fails on the remove_if() line, and I get:
In file included from /usr/include/c++/4.9/utility:70:0,
from /usr/include/c++/4.9/algorithm:60,
from /tmp/b.cpp:1:
/usr/include/c++/4.9/bits/stl_pair.h: In instantiation of ‘std::pair<_T1, _T2>& std::pair<_T1, _T2>::operator=(std::pair<_T1, _T2>&&) [with _T1 = const std::basic_string<char>; _T2 = int]’:
/usr/include/c++/4.9/bits/stl_algo.h:868:23: required from ‘_ForwardIterator std::__remove_if(_ForwardIterator, _ForwardIterator, _Predicate) [with _ForwardIterator = std::__detail::_Node_iterator<std::pair<const std::basic_string<char>, int>, false, true>; _Predicate = __gnu_cxx::__ops::_Iter_pred<main()::<lambda(const value_type&)> >]’
/usr/include/c++/4.9/bits/stl_algo.h:937:47: required from ‘_FIter std::remove_if(_FIter, _FIter, _Predicate) [with _FIter = std::__detail::_Node_iterator<std::pair<const std::basic_string<char>, int>, false, true>; _Predicate = main()::<lambda(const value_type&)>]’
/tmp/b.cpp:12:48: required from here
/usr/include/c++/4.9/bits/stl_pair.h:170:8: error: passing ‘const std::basic_string<char>’ as ‘this’ argument of ‘std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::operator=(const std::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’ discards qualifiers [-fpermissive]
first = std::forward<first_type>(__p.first);
^
Why is this happening? remove_if should not need non-const map keys (strings in this case) - if I am not mistaken. Perhaps the autos assume somehow I want non-const iterators? If so, what do I do other tha spelling out the type (I want to avoid that since this code needs to be templated).
Your example fails even without all those intermediate variables.
unordered_map<string, int> m = { { "hello", 1 }, { "world", 2 } };
auto p = [](const decltype(m)::value_type& e) { return e.second == 2; };
auto it = remove_if(m.begin(), m.end(), p);
The code above will fail with the same errors. You can't use remove_if with associative containers because the algorithm works by moving elements that satisfy your predicate to the end of the container. But how would you reorder an unordered_map?
Write a loop for erasing elements
for(auto it = m.begin(); it != m.end();)
{
if(p(*it)) it = m.erase(it);
else ++it;
}
Or you could package that into an algorithm
template<typename Map, typename Predicate>
void map_erase_if(Map& m, Predicate const& p)
{
for(auto it = m.begin(); it != m.end();)
{
if(p(*it)) it = m.erase(it);
else ++it;
}
}
If you have a standard library implementation that implements the uniform container erasure library fundamentals extensions, then you have an algorithm similar to the one above in the std::experimental namespace.
Don't use std::remove_if for node-based containers. The algorithm attempts to permute the collection, which you either cannot do (for associative containers) or which is inefficient (for lists).
For associative containers, you'll need a normal loop:
for (auto it = m.begin(); it != m.end(); )
{
if (it->second == 2) { m.erase(it++); }
else { ++it; }
}
If you're removing from a list, use the remove member function instead, which takes a predicate.
From cppreference:
Removing is done by shifting (by means of move assignment) the elements in the range in such a way that the elements that are not to be removed appear in the beginning of the range.
You can't reorder the elements in an associative container, for the unordered_map this doesn't make sense because moving the elements to the end doesn't mean anything, they are looked up by keys anyway.

constexpr template functions don't see member array sizes as const expressions

Both clang and gcc fail to compile the code below when ArrayCount is a template. This seems wrong, especially in light of the fact that the sizeof ArrayCount solution work. The template version of ArrayCount is normally a better solution, but it's getting in the way here and constexpr is seemingly not living up to the spirit of its promise.
#if 1
template<typename T, size_t N>
constexpr size_t ArrayCount(T (&)[N])
{
return N;
}
// Results in this (clang): error : static_assert expression is not an integral constant expression
// Results in this (gcc): error: non-constant condition for static assertion, 'this' is not a constant expression
#else
#define ArrayCount(t) (sizeof(t) / sizeof(t[0]))
// Succeeds
#endif
struct X
{
int x[4];
X() { static_assert(ArrayCount(x) == 4, "should never fail"); }
};
The right solution doesn't use homebrew code, but a simple type trait:
int a[] = {1, 2, 3};
#include <type_traits>
static_assert(std::extent<decltype(a)>::value == 3, "You won't see this");
It makes sense to me that this code would fail to compile since ArrayCount is a function taking a non-constexpr argument. According to the standard, I believe this means that ArrayCount must be intstantiated as a non-constexpr function.
There are workarounds, of course. I can think of two off the top of my head (one implemented in terms of the other):
template<typename T> struct ArrayCount;
template<typename T, size_t N>
struct ArrayCount<T[N]> {
static size_t const size = N;
};
template<typename T>
constexpr size_t ArrayCount2() {
return ArrayCount<T>::size;
}
struct X {
int x[4];
X() {
static_assert(ArrayCount<decltype(x)>::size == 4, "should never fail");
static_assert(ArrayCount2<decltype(x)>() == 4, "should never fail");
}
};
It does mean having to use decltype() when you might not wish to, but it does break the pro-forma constraint on taking a non-constexpr parameter.

Resources