Print Vector elements using Boost.Bind - c++

I need to print the values inserted in the vector using Boost.Bind.
Please find the code snippet below:
Please let me know what I am missing here?
class Test
{
int i;
public:
Test() {}
Test(int _i)
{
i = _i;
}
void print()
{
cout << i << ",";
}
};
int main()
{
std::vector<Test> vTest;
Test w1(5);
Test w2(6);
Test w3(7);
vTest.push_back(w1);
vTest.push_back(w2);
vTest.push_back(w3);
std::for_each(vTest.begin(), vTest.end(),boost::bind(boost::mem_fn(&Test::print), _1, ?)); // How do I print Vector elements here?
}

You can do it without boost like this
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
class Test {
int i;
public:
Test() {
}
Test(int _i) {
i = _i;
}
void print() const {
std::cout << i << std::endl;
}
};
int main() {
std::vector<Test> vTest;
Test w1(5);
Test w2(6);
Test w3(7);
vTest.push_back(w1);
vTest.push_back(w2);
vTest.push_back(w3);
// use lambda
std::for_each(vTest.begin(), vTest.end(), [&](const Test& t){ t.print(); });
// use std::bind
std::for_each(vTest.begin(), vTest.end(), std::bind(&Test::print, std::placeholders::_1));
return 0;
}

Maybe you do not want to have the parameter i for your function print() ? If so, you should simply do like this:
std::for_each(vTest.begin(), vTest.end(),boost::bind(&Test::print, _1));
This will output something like this: 5,6,7,. See live.
If you still want to have some argument passed into your function, then you should pass it to bind():
std::for_each(vTest.begin(), vTest.end(),boost::bind(&Test::print, _1, 0));
0 will be your argument for Test::print(). And, in case of your code, you will have next output: 0,0,0,. See live.
If you fix function to next one:
void print(int i)
{
cout << this->i << " " << i << ",";
}
output will be next: 5 0,6 0,7 0,. See live

You don't need bind there.
Just replace the for_each from your code with the below statement.
std::for_each(vTest.begin(), vTest.end(), std::mem_fn(&Test::print)) ;

Related

Creating thread does not work due to arguments being references

I'm currently trying to make my first steps in writing multi-threaded code in CPP and I'm getting a error message that I don't understand at all....
Consider the two functions:
void add_vector(std::vector<int> & vec, int & store){
store = std::accumulate(vec.begin(), vec.end(), 0);
}
int parallel_matrix_sum(std::vector<std::vector<int>> const & mat){
std::vector<std::thread> threads;
std::vector<int> tmp(l);
for (int k =0; k<l; k++){
threads.push_back(std::thread(add_vector, std::cref(mat[k]), std::ref(tmp[k])));
}
for(auto && thread: threads){
thread.join();
}
return std::accumulate(tmp.begin(), tmp.end(), 0);
}
The error I get is
error: attempt to use a deleted function
.
.
.
in instantiation of function template specialization 'std::thread::thread<void (&)(std::vector<int> &, int &), std::reference_wrapper<const std::vector<int>>, std::reference_wrapper<int>, void>' requested here
threads.push_back(std::thread(add_vector, std::cref(mat[k]), std::ref(tmp[k])));
^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/type_traits:1916:5: note: '~__nat' has been explicitly marked deleted here
~__nat() = delete;
Upon googling this issue, all the information points to the fact that std::thread needs to copy the arguments, which cannot be done for references.. The suggested solution seems to be to wrap the arguments in a std::ref call. I am already doing this and it is still not working. Does anybody have some suggestions?
I did some playing. I got this to work:
#include <iostream>
#include <thread>
#include <vector>
void add_vector(const int & a, const int & b, int & c) {
c = a + b;
}
int main() {
std::vector<std::thread> threads;
int a = 5;
int b = 10;
int c = 0;
std::cout << "start threads.\n";
threads.push_back(std::thread(add_vector, a, b, std::ref(c) ));
std::cout << "Join.\n";
for (std::thread &thread: threads) {
thread.join();
}
std::cout << "Done. c == " << c << "\n";
}
This is with g++ using --std=c++17.
I updated this with info from Innocent Bystander. Passing by reference can work if you wrap in std::ref() as shown.
I'm going to try a fresh example with vectors.
#include <iostream>
#include <thread>
#include <vector>
void add_vector(const std::vector<int> & vec, int &result) {
result = 0;
for (const int &value: vec) {
result += value;
}
}
int main() {
std::vector<std::thread> threads;
std::vector<int> values;
std::vector<int> results;
values.push_back(10);
values.push_back(15);
results.push_back(0);
std::cout << "start threads.\n";
threads.push_back(std::thread(add_vector, values, std::ref(results[0]) ));
std::cout << "Join.\n";
for (std::thread &thread: threads) {
thread.join();
}
std::cout << "Done. c == " << results[0] << "\n";
}
This above with vector works. I didn't wrap the first args. I did wrap the final one.
The end answer: take a look at the very first argument to your method. It isn't listed as const.

Sort just one member of the classes in a vector, leaving the other members unchanged

There are tons of answers for sorting a vector of struct in regards to a member variable. That is easy with std::sort and a predicate function, comparing the structs member. Really easy.
But I have a different question. Assume that I have the following struct:
struct Test {
int a{};
int b{};
int toSort{};
};
and a vector of that struct, like for example:
std::vector<Test> tv{ {1,1,9},{2,2,8},{3,3,7},{4,4,6},{5,5,5} };
I do not want to sort the vectors elements, but only the values in the member variable. So the expected output should be equal to:
std::vector<Test> tvSorted{ {1,1,5},{2,2,6},{3,3,7},{4,4,8},{5,5,9} };
I wanted to have the solution to be somehow a generic solution. Then I came up with a (sorry for that) preprocessor-macro-solution. Please see the following example code:
#include <iostream>
#include <vector>
#include <algorithm>
struct Test {
int a{};
int b{};
int toSort{};
};
#define SortSpecial(vec,Struct,Member) \
do { \
std::vector<decltype(Struct::Member)> vt{}; \
std::transform(vec.begin(), vec.end(), std::back_inserter(vt), [](const Struct& s) {return s.Member; }); \
std::sort(vt.begin(), vt.end()); \
std::for_each(vec.begin(), vec.end(), [&vt, i = 0U](Struct & s) mutable {s.Member = vt[i++]; }); \
} while (false)
int main()
{
// Define a vector of struct Test
std::vector<Test> tv{ {1,1,9},{2,2,8},{3,3,7},{4,4,6},{5,5,5} };
for (const Test& t : tv) std::cout << t.a << " " << t.b << " " << t.toSort << "\n";
// Call sort macro
SortSpecial(tv, Test, toSort);
std::cout << "\n\nSorted\n";
for (const Test& t : tv) std::cout << t.a << " " << t.b << " " << t.toSort << "\n";
}
Since macros shouldn't be used in C++, here my questions:
1. Is a solution with the algorithm library possible?
2. Or can this be achieved via templates?
To translate your current solution to a template solution is fairly straight forward.
template <typename T, typename ValueType>
void SpecialSort(std::vector<T>& vec, ValueType T::* mPtr) {
std::vector<ValueType> vt;
std::transform(vec.begin(), vec.end(), std::back_inserter(vt), [&](const T& s) {return s.*mPtr; });
std::sort(vt.begin(), vt.end());
std::for_each(vec.begin(), vec.end(), [&, i = 0U](T& s) mutable {s.*mPtr = vt[i++]; });
}
And we can call it by passing in the vector and a pointer-to-member.
SpecialSort(tv, &Test::toSort);
Somewhow like this (You just need to duplicate, rename and edit the "switchToShort" funtion for the rest of the variables if you want):
#include <iostream>
#include <vector>
struct Test {
int a{};
int b{};
int toSort{};
};
void switchToShort(Test &a, Test &b) {
if (a.toSort > b.toSort) {
int temp = a.toSort;
a.toSort = b.toSort;
b.toSort = temp;
}
}
//void switchToA(Test& a, Test& b) { ... }
//void switchToB(Test& a, Test& b) { ... }
inline void sortMemeberValues(std::vector<Test>& data, void (*funct)(Test&, Test&)) {
for (int i = 0; i < data.size(); i++) {
for (int j = i + 1; j < data.size(); j++) {
(*funct)(data[i], data[j]);
}
}
}
int main() {
std::vector<Test> tv { { 1, 1, 9 }, { 2, 2, 8 }, { 3,3 ,7 }, { 4, 4, 6 }, { 5, 5, 5} };
sortMemeberValues(tv, switchToShort);
//sortMemeberValues(tv, switchToA);
//sortMemeberValues(tv, switchToB);
for (const Test& t : tv) std::cout << t.a << " " << t.b << " " << t.toSort << "\n";
}
With range-v3 (and soon ranges in C++20), you might simply do:
auto r = tv | ranges::view::transform(&Test::toSort);
std::sort(r.begin(), r.end());
Demo

Generating a map of strings to std::list of pointers in c++

I am trying to achieve the creation of such a map. The following code attempts to do this
#include <list>
#include <map>
#include <string>
class IntWithString {
private:
int a;
std::string s;
public:
IntWithString(int a, std::string s) : a(a), s(s) {}
std::string getString() { return s; }
int getInt() { return a; }
};
namespace {
std::map<std::string, std::list<IntWithString *> > m;
}
void appendMap(IntWithString *a) {
auto it = m.find(a->getString());
if (it != m.end()) {
m[a->getString()].push_back(a);
} else {
std::list<IntWithString *> l;
l.push_back(a);
m[a->getString()] = l;
}
}
int main() {
IntWithString a(10, "ten");
IntWithString b(11, "ten");
appendMap(&a);
appendMap(&b);
return 0;
}
However when looking at the map m with the debugger I am getting a map that maps "ten" to a list of size 0. What I would like is a list of size 2.
I am not sure what you mean. If I do:
std::cout << m.size() << ", " << m["ten"].size() << std::endl;
I get this output:
1, 2
which is a map with one key ("ten"), and two values for that key (10 and 11), as expected.
Live demo
PS: Storing pointers in a container like this is a bit uncommon in C++. If you really want to do this though, consider to use Smart Pointers.

c++ class method that takes arbitrary number of callbacks and stores results

I've been trying to think of a way to have my class method take an arbitrary number of callback functions, run all of them, and then store the output. I think this works, but is there a way I can do this where I don't have to make the user wrap all of the callback functions into a vector? This also just feels messy. Feel free to mention other things that are not ideal.
#include <iostream>
#include <functional>
#include <vector>
class MyObj{
public:
// where I store stuff
std::vector<double> myResults;
// function that is called intermittently
void runFuncs(const std::vector<std::function<double()> >& fs){
if ( myResults.size() == 0){
for( auto& f : fs){
myResults.push_back(f());
}
}else{
int i (0);
for( auto& f : fs){
myResults[i] = f();
i++;
}
}
}
};
int main(int argc, char **argv)
{
auto lambda1 = [](){ return 1.0;};
auto lambda2 = [](){ return 2.0;};
MyObj myThing;
std::vector<std::function<double()> > funcs;
funcs.push_back(lambda1);
funcs.push_back(lambda2);
myThing.runFuncs(funcs);
std::cout << myThing.myResults[0] << "\n";
std::cout << myThing.myResults[1] << "\n";
std::vector<std::function<double()> > funcs2;
funcs2.push_back(lambda2);
funcs2.push_back(lambda1);
myThing.runFuncs(funcs2);
std::cout << myThing.myResults[0] << "\n";
std::cout << myThing.myResults[1] << "\n";
return 0;
}
Something like this, perhaps:
template <typename... Fs>
void runFuncs(Fs... fs) {
myResults = std::vector<double>({fs()...});
}
Then you can call it as
myThing.runFuncs(lambda1, lambda2);
Demo

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;
}