I am trying to learn how to use TBB, so I'm modifying a sample program I found that is designed to compute powers of an array of complex numbers. Originally, it was passing an array into the parallel_for loop, but I am trying to change it so that it passes in a vector. However, I cannot get my code to compile; I get the following error (compiled using g++ -g program_name.cpp -ltbb):
error: passing ‘const std::complex<double>’ as ‘this’ argument
discards qualifiers [-fpermissive] result[i] = z;
My code is below:
#include <cstdlib>
#include <cmath>
#include <complex>
#include <ctime>
#include <iostream>
#include <iomanip>
#include "tbb/tbb.h"
#include "tbb/blocked_range.h"
#include "tbb/parallel_for.h"
#include "tbb/parallel_for_each.h"
#include "tbb/task_scheduler_init.h"
using namespace std;
using namespace tbb;
typedef complex<double> dcmplx;
dcmplx random_dcmplx ( void )
{
double e = 2*M_PI*((double) rand())/RAND_MAX;
dcmplx c(cos(e),sin(e));
return c;
}
class ComputePowers
{
vector<dcmplx> c; // numbers on input
int d; // degree
vector<dcmplx> result; // output
public:
ComputePowers(vector<dcmplx> x, int deg, vector<dcmplx> y): c(x), d(deg), result(y) { }
void operator() ( const blocked_range<size_t>& r ) const
{
for(int i=r.begin(); i!=r.end(); ++i)
{
dcmplx z(1.0,0.0);
for(int j=0; j < d; j++) {
z = z*c[i];
};
result[i] = z;
}
}
};
int main ( int argc, char *argv[] )
{
int deg = 100;
int dim = 10;
vector<dcmplx> r;
for(int i=0; i<dim; i++)
r.push_back(random_dcmplx());
vector<dcmplx> s(dim);
task_scheduler_init init(task_scheduler_init::automatic);
parallel_for(blocked_range<size_t>(0,dim),
ComputePowers(r,deg,s));
for(int i=0; i<dim; i++)
cout << scientific << setprecision(4)
<< "x[" << i << "] = ( " << s[i].real()
<< " , " << s[i].imag() << ")\n";
return 0;
}
You're trying to modify non-mutable member field result in const-qualified operator().
Resolve this discrepancy.
Edit #1: I have already mentioned the two keywords above. Either:
Remove const qualifier from operator():
void operator() ( const blocked_range<size_t>& r ) { ... }
Make result mutable:
mutable vector<dcmplx> result;
Additional erorrs may emerge after applying (although strongly preferred) variant no. 1. No. 2 is just for completeness and is used only in marginal situations.
It indeed results in an error with the 1st variant. This is because tbb::parallel_for takes Func by const&, so it can call only const-qualified member functions on your functor. Why? TBB doesn't want to waste performance by copying large functors (STL passes them by value).
I don't know what's the common practice here, I've never used this library.
Edit #2: Probably all you were missing was that result wasn't a reference:
vector<dcmplx> &result;
Now you'll be able to modify it, even in const-qualified operator(). Modifying a member that gets destructed afterwards wouldn't make sense.
Don't forget to change the constructor's signature to pass y by reference, too.
Off topic issues in your code:
Not included <vector> header
using namespace bulky_namespace globally
not using size_t for i in the for-loop
maybe more...
Related
I am writing a code to insert an integer at an index of the string, but after providing the integer to add as string, insert function is not giving the correct output.
It is giving the error that :
no matching member function to call for insert string
This is my code:
#include <iostream>
using namespace std;
int main()
{
string s = "45564528";
int x = 8;
s.insert(s.begin()+5,to_string(x));
cout<<s<<endl;
return 0;
}
The expected output is 455648528.
Looking at the documentation for std::string::insert() shows that it takes a char or an iterator range, not a std::string, which std::to_string() naturally returns. At least, this is the case for the overloads that take an iterator for the first argument.
#include <iostream>
#include <string> // CHANGED: Include what you use
// using namespace std; // CHANGED: Bad practice
int main()
{
std::string s = "45564528";
int x = 8;
// CHANGED: Create string from the int, and use the iterator range overload
// to account for multi-digit numbers
auto tmp = std::to_string(x);
s.insert(s.begin()+5, tmp.begin(), tmp.end());
std::cout << s << '\n'; // CHANGED: std::endl is rarely actually needed
return 0;
}
There is an overload that lets you insert another std::string, but the first argument must be an index and not an iterator. So this would work as well:
#include <iostream>
#include <string>
int main()
{
std::string s = "45564528";
int x = 8;
s.insert(5, std::to_string(x));
std::cout << s << '\n';
return 0;
}
I have an the error "cannot have a cv qualifier" for the function indice_max and I don't understand why, I don't modify at any time the vector v
#include <iostream>
#include <vector>
#include <algorithm>
using std::vector;
int indice_max(const vector<double> & v) const{
int indice =0;
double max = v[0];
for(int i=0; i<v.size(); i++){
if(v[i]>max){
max = v[i];
indice = i;
}
}
return indice;
}
The const qualifier (after the function signature) is used when the class member-function promises not to change any previously assigned value to a data member.
In the given code, there's no class and its private data members. Thus, there's no meaning of using it in this case and a type qualifier isn't allowed on a nonmember function.
I have a code where I have two options, define lambda out of loop to save on lambda creation overhead or define it inside a loop to keep small scope.
Is this choice critical and will make any significant difference?
What are pros and cons of this two choices?
What is best practice?
#include <iostream>
#include <string>
#include <vector>
#include <memory>
int main()
{
std::vector<std::function<void()>> functors;
auto func = [] () { std::cout << "Hello world I am doing some action"; };
//some code here
for(int i = 0; i < 100; ++i)
{
// some code here
functors.push_back(func);
// some code here
}
}
EDITED: simplified example
int main()
{
auto sum = [](const int x, const int y) { return x + y; };
for(int i = 0; i < 100; ++i)
{
std::cout << sum(i, i + 1) << std::endl;
}
}
For each lambda expression, the compiler will create a struct with operator () overloaded for it. It won't create a struct each time the control passes through a lambda, so in terms of generated code it does not matter whether you define it inside or outside the loop. Therefore, keep things local.
As a general rule, don't overthink these illusory optimization issues. Most likely, the performance bottleneck is going to be in your algorithm complexity.
I'd rather wipe out a copy construction and move construct instead by using emplace_back directly (not so useful in this case, but as a rule of thumb one should prefer it whenever possible):
#include <iostream>
#include <string>
#include <vector>
#include <memory>
int main()
{
std::vector<std::function<void()>> functors;
//some code here
for(int i = 0; i < 100; ++i)
{
// some code here
functors.emplace_back([] () { std::cout << "Hello world I am doing some action"; });
// some code here
}
}
That said, I agree with #ArmenTsirunyan and I'd avoid premature optimizations of such a type.
enter image description hereI am trying out some STL programs. I have declared a vector in main and tried to run the program it is working but if i declare the same(vector) inside the class then am getting a compilation error. I think compiler is not recognizing vector(declared inside the class).
I have tried with std:: also still same error. I am using netbeans IDE and cigwin compiler.
please find the code below
#include <cstdlib>
#include <iostream>
#include <vector>
#include <cctype>
using namespace std;
/*
*
*/
class vectorcl
{
vector<int> v(10);
int i;
public:
vectorcl();
void add_vector();
void dis_vector();
};
vectorcl :: vectorcl()
{
for(i =0;i<10 ;i++)
{
v[i] = 0;
}
}
void vectorcl :: dis_vector()
{
cout<< " The vale is : \n";
for(i =0;i<10 ;i++)
{
cout << "\t " <<v[i];
}
}
void vectorcl :: add_vector()
{
for (i =0 ; i<10; i++)
{
v[i] = i+1;
}
}
int main(int argc, char** argv) {
// vector<int> vp(10);
// for(int j =0;j<10 ;j++)
// {
// cout << " " << vp[j];
// }
vectorcl v1;
v1.dis_vector();
v1.add_vector();
v1.dis_vector();
return 0;
}
Please help me in this, my question is why my compiler is not recognizing vector declared inside a class.
error : expected identifier before numeric constant
expected ',' or '...'before numeric constant
Error
You can not use vector<int> v(10); as member variable. The solution is to replace it by vector<int> v; and add this alter the constructor like this:
vectorcl::vectorcl():
v(std::vector<int>(10,0/* This 0 is instead of the for-loop*/)){
}
Or another option is to declare it as :
std::vector<int> v = std::vector<int>(10);
P.S. there is no need to declare int i as class member. Just declare it in every function you need.
From first glance, you are trying to call the constructor in the class prototype: vector<int> v(10);. Your constructor for that class will be called in your wrapper class constructor unless you use a member initialization list.
Edit: using member initialization
vectorcl :: vectorcl(): v(10)
{
}
in an attempt to understand templates better (and thus be able to read basic documentation on c++), I am trying to perform basic operations on arrays as templates. Below is code that defines a function template for averaging an array:
#include <iostream>
#include <array>
using namespace std;
template<class T>
double GetAverage(T tArray[])
{
T tSum = T(); // tSum = 0
int n=tArray.size();
for (int nIndex = 0; nIndex < n; ++nIndex)
{
tSum += tArray[nIndex];
}
// Whatever type of T is, convert to double
return double(tSum) / n;
}
int main ()
{
array<int,5> data={0,1,2,3,4};
cout << GetAverage(data);
cin.get();
return 0;
}
For some reason, as you will see, the compiler runs into issues when dealing with properties of the array, such as array.size(), all within the defining code of a function. I get the following error:
error: no matching function for call to 'GetAverage'
cout << GetAverage(data);
^~~~~~~~~~
note: candidate template ignored: could not match 'T *' against 'array<int, 5>'
double GetAverage(T tArray[])
^
How can I refer to the properties of an object when defining a function which takes in said object as input (all the while using the language of templates)?
C++11 array is a STL container, not a C array thus the following is incorrect:
T tArray[]
A correct version of the above could be
#include <iostream>
#include <array>
#include <numeric>
using namespace std;
template<class T>
double GetAverage(T tArray)
{
// More compact version as suggested by juanchopanza
auto avg = std::accumulate(begin(tArray), end(tArray), 0.0)/tArray.size();
return avg;
}
int main ()
{
array<int,5> data={0,1,2,3,4};
cout << GetAverage(data);
cin.get();
return 0;
}
http://ideone.com/RyPqOr
if you intend to use something more sophisticated you might have to use a struct or a class since functions don't have partial specialization.