i am trying to create a function that parallelize a for.
I am using the Thread of the SFML and std::bind with template.
Here is what i tried.
#include <SFML/System.hpp>
#include <iostream>
#include <functional>
sf::Mutex mutex;
template <typename F>
void For_Multitread(F Function, std::vector<int>& A);
template <typename F>
void Execute_For(F Function, std::vector<int>& A, int Depart, int Fin);
void Compute(int& Number);
template <typename F>
void For_Multitread(F Function, std::vector<int>& A)
{
for (int Thread = 0; Thread < 2; Thread++)
{
sf::Thread thread(std::bind(&Execute_For, Function, A, Thread * 5, (Thread+1)*5));
thread.launch();
}
mutex.lock();
for (int i = 0; i < 10; ++i)
std::cout << A[i] << std::endl;
mutex.unlock();
}
template <typename F>
void Execute_For(F Function, std::vector<int>& A, int Depart, int Fin)
{
for (int i = Depart; i < Fin; ++i)
{
Function(A[i]);
}
}
void Compute(int& Number)
{
Number++;
}
int main()
{
std::vector<int> A;
for (int i =0; i < 10; i++)
A.push_back(i);
For_Multitread(&Compute, A);
return 0;
}
The error is
no matching function for call to 'bind(<unresolved overloaded function type>, void (*&)(int&), std::vector<int>&, int, int)
Did i miss something really important ?
Execute_For is a function template, therefore you need to either supply it with type template arguments:
std::bind(&Execute_For<F>, Function, A, Thread * 5, (Thread+1)*5)
// ~~~~~~~~~~~~~~^
or use a static_cast:
std::bind(static_cast<void(*)(F,std::vector<int>&,int,int)>(&Execute_For), Function, A, Thread * 5, (Thread+1)*5)
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
Related
I have a question about passing the comparison function to sort().
What I want to do is define a sort() function that takes into account for its calculation a member variable of the class that I want to do the sorting in.
Basically, my code looks like this (simplified to only show the relevant parts):
MappingTechnique.h
struct MappingTechnique {
vector<int> usedIndexCount;
};
struct SimpleGreedyMappingTechnique : MappingTechnique {
bool sortByWeights(int index1, int index2);
};
MappingTechnique.m
bool SimpleGreedyMappingTechnique::sortByWeights(int index1, int index2) {
return usedIndexCount[index1] > usedIndexCount[index2];
}
void SimpleGreedyMappingTechnique::processFrame(Frame frame) {
vector<int> payloadIndices = <generate the vector>
// sort the payload indices according to their current usedIndexCount
sort(payloadIndices.begin(), payloadIndices.end(), sortByWeights);
}
This code doesn't compile, it gives the following error:
error: reference to non-static member function must be called
and points to sortByWeights.
Is it even possible to use a member function of a class for sorting? If it is, how I can implement this?
It is, but in general I would encourage just using a proper functor or a lambda:
Using a lambda:
std::sort(payloadIndices.begin(), payloadIndices.end(), [this](int a, int b){
return this->sortByWeights(a, b);
});
Alternatively using std::mem_fn:
auto sorter = std::bind(std::mem_fn(SimpleGreedyMappingTechnique::sortByWeights), this);
std::sort(payloadIndices.begin(), payloadIndices.end(), sorter);
Alternatively using a functor:
namespace{
struct indicies_less_than
{
const SimpleGreedyMappingTechnique & mapping_tech;
indicies_less_than(const SimpleGreedyMappingTechnique & mapping_tech)
:mapping_tech(mapping_tech){}
bool operator()(int a, int b)
{
return mapping_tech.sortByWeights(a, b);
}
};
}
std::sort(payloadIndices.begin(), payloadIndices.end(), indicies_less_than(*this));
Note:
if the types being sorted were anything more complicated than an int you would definitely want to pass them by const& to prevent copying
As mentioned by Mgetz, a functor can be used. Example of functor:
#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <vector>
#define asize 16
class example{
public:
unsigned int a[asize]; // array
std::vector<size_t> v; // indices to array
example(void)
{
v.resize(asize);
for(size_t i = 0; i < asize; i++){
a[i] = rand()%10;
v[i] = i;
}
}
void displayarray(void)
{
for(size_t i = 0; i < asize; i++)
std::cout << std::setw(3) << a[v[i]];
std::cout << std::endl;
}
class lessthan // lessthan functor for std::sort
{
public:
const example &x;
lessthan(const example &e ) : x(e) { }
bool operator()(const size_t & i0, const size_t & i1)
{
return x.a[i0] < x.a[i1];
}
};
void sortarray(void)
{
std::sort(v.begin(), v.end(), lessthan(*this));
}
};
int main()
{
example x;
x.displayarray();
x.sortarray();
x.displayarray();
return 0;
}
I have a third party class Calculation with a function setCallback:
typedef void (*callback_function)(void);
class Calculation
{
public:
void setCallback(callback_function pFunc);
};
and my function I want to use as callback
void callback(int id);
I want to create, say, four (number known at compile time) objects of Calculation and set the callback for each object. I could do something like
void callback0() { callback(0); }
void callback1() { callback(1); }
void callback2() { callback(2); }
void callback3() { callback(3); }
int main() {
std::vector<Calculation> vec;
for (int i = 0; i < 4; i++) {
Calculation c = Calculation();
vec.push_back(c);
}
vec[0].setCallback(callback0);
vec[1].setCallback(callback1);
vec[2].setCallback(callback2);
vec[3].setCallback(callback3);
return 0;
}
Question: How can I achieve this without duplicating and repeating code?
I was thinking of lamdas, like
for (int i = 0; i < 4; i++) {
Calculation c = Calculation();
c.setCallback([i]() -> void {callback(i);});
vec.push_back(c);
}
but a lambda can only be converted to a function pointer if it does not capture.
Template function might help:
template <int N>
void callbackN() { callback(N); }
and then
vec[0].setCallback(callback<0>);
vec[1].setCallback(callback<1>);
vec[2].setCallback(callback<2>);
vec[3].setCallback(callback<3>);
Since the number of Calculation instances is known at compile-time, you set up something like this to automate things, but not sure if it's worth the effort:
template <size_t Size, typename Idx = std::make_index_sequence<Size>>
class CalcInterface {
std::array<callback_function, Size> m_callbacks { makeCallbacks(Idx{}) };
std::array<Calculation, Size> m_calcs;
protected:
template <size_t N>
static inline callback_function makeCallback() {
return []{ return callback(N); };
}
template <size_t... Seq>
static inline auto makeCallbacks(std::index_sequence<Seq...>) {
std::array<callback_function, Size> arr;
((arr[Seq] = makeCallback<Seq>()), ...);
return arr;
}
static void callback(int id) {
std::cout << "Callback #" << id << " was called\n";
}
public:
CalcInterface() {
for (size_t i=0; i<Size; ++i) {
m_calcs[i].setCallback(m_callbacks[i]);
}
}
void runAll() const {
for (auto& calc: m_calcs) calc.run();
}
};
Example here: https://godbolt.org/z/sWTzn59ce
I want to implement Functional Object in Polymorphism as follows:
#include <algorithm>
#include <iostream>
using namespace std;
struct Compare {
virtual bool operator() (int, int) const = 0;
};
struct Less : public Compare {
bool operator() (int i, int j)
const {
return (i < j);
}
};
struct Greater : public Compare {
bool operator() (int i, int j)
const {
return (i > j);
}
};
void f(const Compare& c) {
int arr[10] = { 4,2,6,7,1,3,5,9,8,0 };
sort(arr, arr + 10, c);
for (int i = 0; i < 10; ++i)
cout << arr[i] << " ";
}
int main()
{
f(Less());
f(Greater());
}
But it has an error message "no instance of overloaded function "sort" matches the argument list"
I think that the abstract class cannot have an instance.
How can I fix it?
std::sort wants to copy the ordering function.
There is a standard class that "wraps" a reference and makes it copyable; std::ref.
#include <memory>
... and then ...
sort(arr, arr + 10, std::ref(c));
std::sort takes the comparator parameter by-value; you can't pass an abstract class like Compare to it. You can pass Less or Greater directly to it.
You can make f template,
template <typename C>
void f(const C& c) {
int arr[10] = { 4,2,6,7,1,3,5,9,8,0 };
sort(arr, arr + 10, c);
for (int i = 0; i < 10; ++i)
cout << arr[i] << " ";
}
then pass Less or Greater to it like:
f(Less());
f(Greater());
LIVE
Hi I have assignment that Sort array of Fraction of any types ( Ascending or Desceding)
But when I call function doSomething It's wrong.
template <class T>
struct Fraction {
T num, denom; //num - Numerator ; demon-Denominator
};
template <class T>
void AscendingArrayFraction(Fraction<T> a[], int n)
{
for (int i = 0;i < n;i++) {
for (int j = i + 1;j < n;j++) {
if (compareFraction(a[i], a[j]))
swapFraction(a[i], a[j]);
}
}
}
template <class T>
void DescendingArrayFraction(Fraction<T> a[], int n)
{
for (int i = 0;i < n;i++) {
for (int j = i + 1;j < n;j++) {
if (!compareFraction(a[i], a[j]))
swapFraction(a[i], a[j]);
}
}
}
template <class T>
void doSomething(Fraction<T> a[], int n, T(*p) (Fraction<T>, int)) {
return p(a,n);
}
int main()
{
Fraction<int> a[100];
int n;
inputFraction(a, n);
doSomething(a, n, AscendingArrayFraction(a,n)); // It's have a problem right here
}
It seems that I still don't understand this lesson (Abstraction). Can you help me fix function doSomething??
Seems to me you are getting confused about the use of a function pointer (p in doSomething). Normally when you use a function pointer in a sorting algorithm the purpose of the function pointer is to compare two objects. So you have only one sorting function which you can customise with different comparison functions. It looks like that is what you were trying to write but you've got it mixed up somewhere.
Instead you have two sorting functions AscendingArrayFraction and DescendingArrayFraction, no comparison functions (compareFraction isn't defined anywhere) and a function called doSomething whose purpose is obscure.
This (in outline) is how the code should look
// true if a < b, false otherwise
template <class T>
bool compareFractionsAscending(Fraction<T> a, Fraction<T> b) {
...
}
// true if a > b, false otherwise
template <class T>
bool compareFractionsDescending(Fraction<T> a, Fraction<T> b) {
...
}
// sort array using compareFractions function pointer
template <class T>
void sortFractions(Fraction<T> a[], int n, bool (*compareFractions)(Fraction<T>, Fraction<T>)) {
...
}
int main()
{
Fraction<int> a[100];
int n;
inputFraction(a, n);
sortFractions(a, n, compareFractionsAscending<int>);
}
I have a question about passing the comparison function to sort().
What I want to do is define a sort() function that takes into account for its calculation a member variable of the class that I want to do the sorting in.
Basically, my code looks like this (simplified to only show the relevant parts):
MappingTechnique.h
struct MappingTechnique {
vector<int> usedIndexCount;
};
struct SimpleGreedyMappingTechnique : MappingTechnique {
bool sortByWeights(int index1, int index2);
};
MappingTechnique.m
bool SimpleGreedyMappingTechnique::sortByWeights(int index1, int index2) {
return usedIndexCount[index1] > usedIndexCount[index2];
}
void SimpleGreedyMappingTechnique::processFrame(Frame frame) {
vector<int> payloadIndices = <generate the vector>
// sort the payload indices according to their current usedIndexCount
sort(payloadIndices.begin(), payloadIndices.end(), sortByWeights);
}
This code doesn't compile, it gives the following error:
error: reference to non-static member function must be called
and points to sortByWeights.
Is it even possible to use a member function of a class for sorting? If it is, how I can implement this?
It is, but in general I would encourage just using a proper functor or a lambda:
Using a lambda:
std::sort(payloadIndices.begin(), payloadIndices.end(), [this](int a, int b){
return this->sortByWeights(a, b);
});
Alternatively using std::mem_fn:
auto sorter = std::bind(std::mem_fn(SimpleGreedyMappingTechnique::sortByWeights), this);
std::sort(payloadIndices.begin(), payloadIndices.end(), sorter);
Alternatively using a functor:
namespace{
struct indicies_less_than
{
const SimpleGreedyMappingTechnique & mapping_tech;
indicies_less_than(const SimpleGreedyMappingTechnique & mapping_tech)
:mapping_tech(mapping_tech){}
bool operator()(int a, int b)
{
return mapping_tech.sortByWeights(a, b);
}
};
}
std::sort(payloadIndices.begin(), payloadIndices.end(), indicies_less_than(*this));
Note:
if the types being sorted were anything more complicated than an int you would definitely want to pass them by const& to prevent copying
As mentioned by Mgetz, a functor can be used. Example of functor:
#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <vector>
#define asize 16
class example{
public:
unsigned int a[asize]; // array
std::vector<size_t> v; // indices to array
example(void)
{
v.resize(asize);
for(size_t i = 0; i < asize; i++){
a[i] = rand()%10;
v[i] = i;
}
}
void displayarray(void)
{
for(size_t i = 0; i < asize; i++)
std::cout << std::setw(3) << a[v[i]];
std::cout << std::endl;
}
class lessthan // lessthan functor for std::sort
{
public:
const example &x;
lessthan(const example &e ) : x(e) { }
bool operator()(const size_t & i0, const size_t & i1)
{
return x.a[i0] < x.a[i1];
}
};
void sortarray(void)
{
std::sort(v.begin(), v.end(), lessthan(*this));
}
};
int main()
{
example x;
x.displayarray();
x.sortarray();
x.displayarray();
return 0;
}