Calling a generic lambda in boost::mpl::for_each() - c++

A few answers here (How to loop through a boost::mpl::list? being the one I started with) imply that I should be able to construct a generic lambda to feed to a boost::mpl::for_each() but I'm unable to find a working example, or build one myself.
Idealy what I would like to be able to do in a lambda is take a function like
template<typename T>
void TestFunction(const int &p)
{
T t(p);
std::cout << "p = " << p << ", t = " << t << std::endl;
};
that I'm currently calling in a loop with something like
for(int k = 0; k < 2; ++k)
{
TestFunction<int>(k);
TestFunction<long>(k);
TestFunction<float>(k);
TestFunction<double>(k);
};
and replace it with something like
typedef boost::mpl::list<int, long, float, double> ValidTypes;
for(int k = 0; k < 2; ++k)
{
// lambda definition that captures k
// boost::mpl::for_each(ValidTypes, ...) that calls the lambda.
};
Is this possible? If not with for_each() with one of the other mpl constructs? I've got a version of the code running where I overload operator() but I'd like to see a lambda solution if it's possible.
Thanks,
Andy.

If you can use C++14's generalized lambdas, you can capture the value of p and also infer the type of the current valid type being passed to the lambda:
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/list.hpp>
#include <iostream>
int main()
{
using ValidTypes = boost::mpl::list<int, long, float, double>;
for (auto k = 0; k < 2; ++k) {
boost::mpl::for_each<ValidTypes>([p = k](auto arg) {
using T = decltype(arg);
T t(p);
std::cout << "p = " << p << ", t = " << t << '\n';
});
}
}
Live Example.
Edit: for extra credit, here's a slightly more advanced version that also works for non-default constructible types:
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/list.hpp>
#include <iostream>
class NonDefaultConstructible
{
int value;
public:
NonDefaultConstructible(int const& p) : value(p) {}
friend auto& operator<<(std::ostream& ostr, NonDefaultConstructible const& ndc)
{
return ostr << ndc.value;
}
};
int main()
{
using ValidTypes = boost::mpl::list<int, long, float, double, NonDefaultConstructible>;
for (auto k = 0; k < 2; ++k) {
boost::mpl::for_each<ValidTypes, boost::mpl::make_identity<boost::mpl::_1>>([p = k](auto arg) {
using T = typename decltype(arg)::type;
T t(p);
std::cout << "p = " << p << ", t = " << t << '\n';
});
}
}
Live Example.
For an explanation of the somewhat convoluted use of make_identity, see my very first Q&A here!

Related

How can I access the element of my own array class by the square brackets overload?

Take a look at this simplified version of what I'm coding and you'll understand the problem...
#include <iostream>
template<typename T, int N = 2>
class Array
{
T m_arr[N]{ 0 };
int m_size = N;
public:
T& operator[](const int& index) { return m_arr[index]; }
};
int main()
{
Array<int, 10>* thing = new Array<int, 10>();
thing[2] = 5;
std::cout << thing[2] << std::endl;
}
Now, obviously the first thing that comes to mind is, hey, just like I overloaded the [] operator, lets overload the = and the << operators, but that wouldn't work, since that is only valid for doing something like this...
thing = whatever;
std::cout << thing << std::endl;
But how could I do it for...
thing[num] = whatever;
std::cout << thing[num] << std::endl;

How to create my own loop version in C++?

I was wondering if it possible to create custom functions like for, for_each, while etc.
There's nothing that I want to do that the existing loops won't do it. I am just curious to learn how they work and if I ever need to create my own.
For example if one wants to create another version of the for function that would take only parameter.
In this example, I want to to create a for that only takes one parameter, an integer.
Instead of writing
for (int i = 0; i < 50; ++i)
I would create a for version like this
for_(50)
and they would act the same. How would I do something like that?
I have posted this question in another forum.
In addition to the proposals in other answers, you could create a function like the one below, but it is, at the very end, very similar to using the standard std::for_each.
#include <iostream>
#include <functional>
template<typename C, typename F>
void for_(C begin_, C end_, F&& f) { // [begin_, end_)
for (C i = begin_; i < end_; ++i) {
f(i);
}
}
template<typename C, typename F>
void for_(C count, F&& f) { // special case for [0, count)
for_(0, count, f);
}
void mul2(int x) {
std::cout << x*2 << " ";
}
int main() {
for_(10, [](int i) { std::cout << i << "\n"; });
for_(2, 10, mul2);
}
An ugly and unsafe solution is to use macro:
#define REPEAT(i,N) for(int (i) = 0; (i) < (N); ++(i))
int main()
{
REPEAT(i,10) std::cout << i << std::endl;
return 0;
}
You can't extend the C++ syntax for new loops.
You could use a macro, but this is pretty ugly, and generally best avoided. Another way to get something similar is by passing a functor as a parameter, greatly helped by the introduction of lambda expressions to C++. You can find some examples of such in the <algorithm> header.
For example:
#include <algorithm>
#include <vector>
int main()
{
std::vector<int> numbers = { 1, 4, 5, 7, 10 };
int even_count = 0;
for (auto x : numbers)
{
if (x % 2 == 0)
{
++even_count;
}
}
auto even_count2 = std::count_if(numbers.begin(), numbers.end(), [](int x) { return x % 2 == 0; });
}
You could use a lambda function and pass in a function object as a parameter to be performed for every iteration of the loop.
#include <iostream>
#include <functional>
int main()
{
auto for_ = [](int start, int size, std::function<void (int i)> fn)
{
int end = start + size;
for (int i = start; i < end; ++i)
{
fn(i);
}
};
for_(0, 10, [](int i) { std::cout << i << std::endl; });
for_(0, 10, [](int i) { std::cout << i*2 << std::endl; });
}
It seems like you are reinventing the wheel here a bit. You could just use std::for_each.
However, you could have custom lambda functions that do different things and just implement the operation within the lambda itself without taking in a function object for the operation.

Using c++ std::copy on an array of structure

I want to use std::copy to copy an existing array of structures to new one. A regular option is fine with '''local_copy()'''. I want to know the procedure to use std::copy for such case described below -
I tried the code and get following error at compile time
#include <iostream>
class BigClass{
public:
struct Astruct{
double x[2], v[2];
int rank;
}one_struct;
};
void allocate(struct BigClass::Astruct& one_struct, int i)
{
one_struct.x[0] = 1.1;
one_struct.x[1] = 1.2;
one_struct.v[0] = 2.1;
one_struct.v[1] = 2.2;
one_struct.rank = i;
}
void local_copy(struct BigClass::Astruct& dest, struct BigClass::Astruct& source)
{
dest.x[0] = source.x[0];
dest.x[1] = source.x[1];
dest.v[0] = source.v[0];
dest.v[1] = source.v[1];
dest.rank = source.rank;
}
void print(struct BigClass::Astruct one_struct)
{
std::cout << one_struct.rank << " " << one_struct.x[0] << " " << one_struct.x[1] << " " << one_struct.v[0] << " " << one_struct.v[1] << "\n";
}
int main(int argc, char *argv[]) {
int size = 10;
struct BigClass::Astruct BCobj[size];
for(int i = 0; i < size; i++) allocate(BCobj[i], i);
for(int i = 0; i < size; i++) print(BCobj[i]);
struct BigClass::Astruct second_BCobj[size];
//for(int i = 0; i < size; i++) local_copy(second_BCobj[i], BCobj[i]); // this works
for(int i = 0; i < size; i++) std::copy(BCobj[i+1], BCobj[i], second_BCobj[i]); // not working
for(int i = 0; i < size; i++) print(BCobj[i]);
}
The compile time error is following -
/usr/include/c++/7/bits/stl_algobase.h:377:57: error: no type named ‘value_type’ in ‘struct std::iterator_traits<BigClass::Astruct>’
typedef typename iterator_traits<_II>::value_type _ValueTypeI;
^~~~~~~~~~~
/usr/include/c++/7/bits/stl_algobase.h:378:57: error: no type named ‘value_type’ in ‘struct std::iterator_traits<BigClass::Astruct>’
typedef typename iterator_traits<_OI>::value_type _ValueTypeO;
^~~~~~~~~~~
/usr/include/c++/7/bits/stl_algobase.h:379:64: error: no type named ‘iterator_category’ in ‘struct std::iterator_traits<BigClass::Astruct>’
typedef typename iterator_traits<_II>::iterator_category _Category;
^~~~~~~~~
/usr/include/c++/7/bits/stl_algobase.h:383:9: error: no type named ‘value_type’ in ‘struct std::iterator_traits<BigClass::Astruct>’
const bool __simple = (__is_trivial(_ValueTypeI)
~~~~~~~~~~~~~~~~~~~~~~~~~~
&& __is_pointer<_II>::__value
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
&& __is_pointer<_OI>::__value
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
&& __are_same<_ValueTypeI, _ValueTypeO>::__value);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/7/bits/stl_algobase.h:386:44: error: no type named ‘iterator_category’ in ‘struct std::iterator_traits<BigClass::Astruct>’
return std::__copy_move<_IsMove, __simple,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
_Category>::__copy_m(__first, __last, __result);
~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~
Some examples for vectors and int datatypes are available. Could anyone elaborate the appropriate sequence for std::copy for this kind of code structure?
Thanks.
std::copy is used instead of for loop, not with one.
std::copy(BCobj, BCobj + size, second_BCobj);
is essentially the same as
for(int i = 0; i < size; ++i) {
second_BCobj[i] = BCobj[i];
}
Also, don't forget to #include <algorithm> for std::copy
Explanation of arguments for std::copy:
std::copy takes as arguments 2 arguments of type matching InputIterator requirements and single argument of type OutputIteretor. Fortunately, pointers match these requirements, so we can use them directly. And because array name is interpreted as a pointer to its first element, we can pass it directly as argument to std::sort
Better version as suggested by Chef Gladiator:
std::copy(std::begin(BCobj), std::end(BCobj), std::begin(second_BCobj))
Welcome to Stack Overflow. You have presented your full code. Please next time also describe the development environment you are building in. Even better, try to present operating system agnostic and compiler agnostic, standard C++ code.
This is C++ forum, so we like to use standard C++ here. Your code is rewritten bellow using std::array. That makes it simple. Please study and enjoy the standard C++.
#include <array>
#include <iostream>
#include <algorithm>
namespace stack_overflow {
using namespace std;
struct BigClass final {
struct Astruct final {
double x[2], v[2];
int rank;
}one_struct;
friend ostream& operator << (ostream& os, Astruct const & one_struct)
{
return os << one_struct.rank << " " << one_struct.x[0] << " "
<< one_struct.x[1] << " " << one_struct.v[0] << " "
<< one_struct.v[1] ;
}
};
constexpr int size = 10;
using bcobj_arr = std::array<BigClass::Astruct, size>;
void populate( bcobj_arr& bcobjects_)
{
int j{ 0 };
for (auto& one_struct : bcobjects_) {
one_struct.x[0] = 1.1;
one_struct.x[1] = 1.2;
one_struct.v[0] = 2.1;
one_struct.v[1] = 2.2;
one_struct.rank = j++;
}
}
void print(const char prompt[BUFSIZ], bcobj_arr const & bcobjects_ )
{
cout << "\n\n" << prompt << "\n\n" ;
for (auto& one_struct : bcobjects_) {
cout << one_struct << "\n";
}
}
bool test (int argc, const char* argv[])
{
bcobj_arr BCobj;
populate(BCobj);
print("BCobj", BCobj);
// std::array instances can be copied
bcobj_arr second_BCobj = BCobj ;
print("second_BCobj", second_BCobj);
return true;
}
}
int main(const int argc, const char * argv[])
{
stack_overflow::test(argc, argv);
return 42;
}
Code is not commented at all. I assume you have a lot of questions, please do ask, in the comments bellow. I will try and answer them all by pointing you to the relevant documentation on-line.

Cannot Return Values When Passing Function by Reference To TBB Task

I'm getting my feet wet with Intel TBB and am trying to figure out why I cannot populate a vector passed in by reference to a TBB Task when I also pass in a function by reference.
Here is the code:
// tbbTesting.cpp : Defines the entry point for the console application.
#include "stdafx.h"
#include "tbb/task.h"
#include <functional>
#include <iostream>
#include <random>
#define NUM_POINTS 10
void myFunc(std::vector<double>& numbers)
{
std::mt19937_64 gen;
std::uniform_real_distribution<double> dis(0.0, 1000.0);
for (size_t i = 0; i < NUM_POINTS; i++)
{
auto val = dis(gen);
std::cout << val << std::endl; //proper values generated
numbers.push_back(val); //why is this failing?
}
std::cout << std::endl;
for (auto i : numbers)
{
std::cout << numbers[i] << std::endl; //garbage values
}
}
class TASK_generateRandomNumbers : public tbb::task
{
public:
TASK_generateRandomNumbers(std::function<void(std::vector<double>&)>& fnc,
std::vector<double>& nums) : _fnc(fnc), _numbers(nums) {}
~TASK_generateRandomNumbers() {};
tbb::task* execute()
{
_fnc(_numbers);
return nullptr;
}
private:
std::function<void(std::vector<double>&)>& _fnc;
std::vector<double>& _numbers;
};
class Manager
{
public:
Manager() { _numbers.reserve(NUM_POINTS); }
~Manager() {}
void GenerateNumbers()
{
_fnc = std::bind(&myFunc, _numbers);
TASK_generateRandomNumbers* t = new(tbb::task::allocate_root())
TASK_generateRandomNumbers(_fnc, _numbers);
tbb::task::spawn_root_and_wait(*t);
}
auto GetNumbers() const { return _numbers; }
private:
std::function<void(std::vector<double>&)> _fnc;
std::vector<double> _numbers;
};
int main()
{
Manager mgr;
mgr.GenerateNumbers();
auto numbers = mgr.GetNumbers(); //returns empty
}
When the execute method performs the operation, I can get values when passing the vector by reference.
When the execute method has to call a function, I get garbage data printed to the console (push_back failing?) and I get an empty container on return.
Can anyone see what I'm missing? Thanks.
I have found a couple of bugs that have nothing to do with tbb.
1) Your myFunc is using range for incorrectly. It does not return an index but each value directly in the vector in turn. Your code is casting each double to an int and using that as index into the array which is why you are gettign garbage.
2) When you use std::bind to create a functor the arguments are copied by value. If you want to pass in a reference then you need to use std::ref to wrap the argument.
If you are using c++11 then you might want to consider using a lambda rather than bind.
I've written a small program using your myFunc in different ways: with and without using std::ref and also a lambda example. You should see that it generates the same numbers 3 times but when it tries to print out v1 it wont contain anything because the generated values were placed in a copy.
#include <vector>
#include <random>
#include <iostream>
#include <functional>
constexpr size_t NUM_POINTS = 10;
void myFunc(std::vector<double>& numbers)
{
std::mt19937_64 gen;
std::uniform_real_distribution<double> dis(0.0, 1000.0);
for (size_t i = 0; i < NUM_POINTS; i++)
{
auto val = dis(gen);
std::cout << val << std::endl; //proper values generated
numbers.push_back(val); //why is this failing? it's not
}
std::cout << std::endl;
}
void printNumbers(std::vector<double>const& numbers)
{
for (auto number : numbers)
{
std::cout << number << std::endl;
}
std::cout << std::endl;
}
int main()
{
std::cout << "generating v1" << std::endl;
std::vector<double> v1;
auto f1 = std::bind(&myFunc, v1);
f1();
printNumbers(v1);
std::cout << "generating v2" << std::endl;
std::vector<double> v2;
auto f2= std::bind(&myFunc, std::ref(v2));
f2();
printNumbers(v2);
std::cout << "generating v3" << std::endl;
std::vector<double> v3;
auto f3 = [&v3]() { myFunc(v3); }; //using a lambda
f3();
printNumbers(v3);
return 0;
}

C++ Sign function - From MatLab?

I'm trying to re-write some MatLab code in C++ and I've come across this:
currentsign = sign(vector(i));
I have looked on the internet and found this link: http://www.mathworks.co.uk/help/techdoc/ref/sign.html
I'm just wondering if there's a sign function in C++? If not, can anyone suggest any tutorials on creating it.
Thank you :)
template <typename T>
int sign (const T &val) { return (val > 0) - (val < 0); }
Credit due to Ambroz Bizjak.
template <typename T>
std::vector<int> sign (const std::vector<T> &v) {
std::vector<int> r(v.size());
std::transform(v.begin(), v.end(), r.begin(), (int(*)(const T&))sign);
return r;
}
Full example on ideone.
I would suggest
First, write a function of functor that takes a single element and returns 1, -1 or 0 depending on the element's value
Second, use std::transform together with this function/functor to take an input container and fill a second container with the desired values
template <typename T>
int signum(const T& val) {
// implement signum logic
}
#include <vector>
#include <algorithm>
int main() {
std::vector<int> data = ....;
std::vector<int> signs(data.size());
std::transform(data.begin(), data.end(), signs.begin(), signum<int>);
}
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <vector>
inline int get_signum(int val) {
return val < 0 ? -1
: val == 0 ? 0
: 1;
}
int main() {
std::vector<int> values;
for (int i = -5; i < 6; ++i)
values.push_back(i);
std::vector<int> signum(values.size());
std::transform(values.begin(), values.end(), signum.begin(), get_signum);
for (int i = 0; i < values.size(); ++i) {
std::cout << std::setw(2) << values[i] << ' ' << signum[i] << std::endl;
}
return 0;
}
Well You can do It at compile time using template Specialization.
You can use sign<n>::Positive, sign<n>::Negetive and sign<n>::Zero also you can use sign<n>::Sign which is 1|0|-1 which is same as sign of Matlab.
#include <iostream>
template<int n>
struct sign{
enum{
Positive = (n > 0),
Negetive = (n < 0),
Zero = 0,
Sign = ((n > 0) ? 1 : -1)
};
};
template<>
struct sign<0>{
enum{
Positive = 0,
Negetive = 0,
Zero = 1,
Sign = 0
};
};
int main(){
std::cout << sign<0>::Positive << sign<0>::Negetive << sign<0>::Zero << sign<0>::Sign << std::endl;
std::cout << sign<1>::Positive << sign<1>::Negetive << sign<1>::Zero << sign<1>::Sign << std::endl;
std::cout << sign<-1>::Positive << sign<-1>::Negetive << sign<-1>::Zero << sign<-1>::Sign << std::endl;
return 0;
}
You used to do sign(n) there and here you will do sign<n>::Sign.
C99 has signbit() and copysign(), which seem to be implemented in glibc on Linux. You didn't specify what platform you're on though, so I'm not sure that helps...