When compiling the program below, I get the error message:
Error 1 error C2228: left of '.get_future' must have class/struct/union c:\users\haliaga\documents\visual studio 2010\projects\test\test\accumulateexceptionsafe.cpp 62 1 Test
which is not actually the real problem.
if you comment the lines:
//futures[i]=task.get_future();
//threads[i]=std::thread(std::move(task),block_start,block_end);
//block_start=block_end;
you'll get the warning below, that says that "tasK" was not called:
*warning C4930: 'std::packaged_task<> task(accumulate_block (__cdecl )(void))': prototyped function not called (was a variable definition intended?)
1> with
1> [
1> =int (std::_List_iterator>>,std::_List_iterator>>),
1> Iterator=std::_List_iterator>>,
1> T=int
1> ]
what would be the proper way of specifying:
std::packaged_task<T(Iterator,Iterator)> task(accumulate_block<Iterator,T>());
?
Thank you
PS: find below the code:
#include <list>
#include <numeric>
#include <vector>
#include <thread>
#include <future>
using namespace std;
template<typename Iterator,typename T>
struct accumulate_block
{
T operator()(Iterator first, Iterator last)
{
std::thread::id id = std::this_thread::get_id();
return std::accumulate(first, last, T());
}
};
class join_threads
{
std::vector<std::thread>& threads;
public:
explicit join_threads(std::vector<std::thread>& threads_):
threads(threads_)
{
std::thread::id id = std::this_thread::get_id();
}
~join_threads()
{
std::thread::id id = std::this_thread::get_id();
for(unsigned long i=0;i<threads.size();++i)
{
if(threads[i].joinable())
threads[i].join();
}
}
};
template<typename Iterator,typename T>
T parallel_accumulate(Iterator first,Iterator last,T init)
{
std::thread::id id = std::this_thread::get_id();
unsigned long const length=std::distance(first,last);
if(!length)
return init;
unsigned long const min_per_thread=25;
unsigned long const max_threads=(length+min_per_thread-1)/min_per_thread;
unsigned long const hardware_threads=std::thread::hardware_concurrency();
unsigned long const num_threads=std::min(hardware_threads!=0?hardware_threads:2,max_threads);
unsigned long const block_size=length/num_threads;
std::vector<std::future<T> > futures(num_threads-1);
std::vector<std::thread> threads(num_threads-1);
join_threads joiner(threads);
Iterator block_start=first;
for(unsigned long i=0;i<(num_threads-1);++i)
{
Iterator block_end=block_start;
std::advance(block_end,block_size);
std::packaged_task<T(Iterator,Iterator)> task(accumulate_block<Iterator,T>());
futures[i]=task.get_future();
threads[i]=std::thread(std::move(task),block_start,block_end);
block_start=block_end;
}
T last_result=accumulate_block<Iterator, T>()(block_start,last);
T result=init;
for(unsigned long i=0;i<(num_threads-1);++i)
{
result+=futures[i].get();
}
result += last_result;
return result;
};
int main()
{
list<int> l;
for(int i=0; i<26; ++i)
l.push_back(i);
std::thread::id id = std::this_thread::get_id();
int res = ::parallel_accumulate(l.begin(), l.end(), 0);
return 0;
}
Most vexing parse.
std::packaged_task<T(Iterator,Iterator)> task(accumulate_block<Iterator,T>());
declares a function called task that takes a parameter of type pointer to function taking no arguments and returning a accumulate_block<Iterator,T> and returns a std::packaged_task<T(Iterator,Iterator)>.
Disambiguate using the uniform initialization syntax:
std::packaged_task<T(Iterator,Iterator)> task(accumulate_block<Iterator,T>{});
Or with an extra pair of parentheses for ancient compilers that doesn't have support for uniform initialization:
std::packaged_task<T(Iterator,Iterator)> task((accumulate_block<Iterator,T>()));
// ^ ^
Related
I'm trying to adapt an example from Stroustrup C++ 4th Ed Page 1182, to call a function from operator()() vs the bind. Unfortunately, I'm getting a number of compilation errors. The code that worked before is // commented out. Does anyone know how to resolve the errors?
#include <iostream>
#include <random>
#include <map>
#include <functional>
using namespace std;
class rand_int {
public:
rand_int(int lo, int hi) : p{lo,hi}, re{rd()} {}
// int operator()() const { return r(); }
int operator()() const { return
uniform_int_distribution<>{p}(re); }
private:
uniform_int_distribution<>::param_type p;
random_device rd;
default_random_engine re;
// function<int()> r = bind(uniform_int_distribution<>{p}, re);
};
int main()
{
map<int,int> m;
rand_int ri{0,9};
for (int i=0; i < 100; ++i) {
m[ri()]++;
}
for (map<int,int>::iterator it = m.begin();
it != m.end(); ++it)
cout << it->first << ", " << it->second << '\n';
return 0;
}
Compilation:
clang++ -Wall -std=c++11 -pedantic test252.cc && ./a.out
In file included from test252.cc:2:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/random:49:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/random.h:35:
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/uniform_int_dist.h:243:25: error:
no matching function for call to object of type 'const
std::linear_congruential_engine<unsigned long, 16807, 0, 2147483647>'
__ret = __uctype(__urng()) - __urngmin;
^~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/uniform_int_dist.h:166:24: note:
in instantiation of function template specialization
'std::uniform_int_distribution<int>::operator()<const
std::linear_congruential_engine<unsigned long, 16807, 0, 2147483647> >'
requested here
{ return this->operator()(__urng, _M_param); }
^
test252.cc:12:35: note: in instantiation of function template specialization
'std::uniform_int_distribution<int>::operator()<const
std::linear_congruential_engine<unsigned long, 16807, 0, 2147483647> >'
requested here
uniform_int_distribution<>{p}(re); }
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/random.h:323:7: note:
candidate function not viable: 'this' argument has type 'const
std::linear_congruential_engine<unsigned long, 16807, 0, 2147483647>', but
method is not marked const
operator()()
^
This line:
uniform_int_distribution<>{p}(re);
modifies the member re. So the operator() can't be marked const.
You need to do:
int operator()() { // non-const method
return uniform_int_distribution<>{p}(re);
}
Here's a demo.
Hello everybody hope all is well. I am trying to work with threads in c++. I compiled the code and got the following error messages.
C:\Users\Peretz\Documents\keylogger\KeyConstants.h|183|warning: unknown escape sequence: '\|' [enabled by default]|
C:\Users\Peretz\Documents\keylogger\Timer.h|10|error: 'thread' in namespace 'std' does not name a type|
C:\Users\Peretz\Documents\keylogger\Timer.h||In member function 'void Timer::SleepAndRun()':|
C:\Users\Peretz\Documents\keylogger\Timer.h|25|error: 'std::this_thread' has not been declared|
C:\Users\Peretz\Documents\keylogger\Timer.h||In member function 'void Timer::Start(bool)':|
C:\Users\Peretz\Documents\keylogger\Timer.h|71|error: 'Thread' was not declared in this scope|
C:\Users\Peretz\Documents\keylogger\Timer.h|71|error: 'thread' is not a member of 'std'|
C:\Users\Peretz\Documents\keylogger\Timer.h||In member function 'void Timer::Stop()':|
C:\Users\Peretz\Documents\keylogger\Timer.h|82|error: 'Thread' was not declared in this scope|
||=== Build failed: 5 error(s), 1 warning(s) (0 minute(s), 0 second(s)) ===|
I looked on Youtube for threads in c++ and threads in c++11 but could not find an answer. Please explain why there are these errors.
#ifndef TIMER_H
#define TIMER_H
#include <thread>
#include <chrono>
class Timer
{
std::thread Thread;
bool Alive = false;
long CallNumber = -1L;
long repeat_count = -1L;
std::chrono::milliseconds interval = std::chrono::milliseconds(0);
std::function<void(void)> funct = nullptr;
void SleepAndRun ()
{
std::this_thread::sleep_for(interval);
if (Alive)
{
Function ()();
}
}
void ThreadFunc ()
{
if (CallNumber == Infinite)
while (Alive)
SleepAndRun ();
else
while (repeat_count--)
SleepAndRun ();
}
public:
static const long Infinite = -1L;
Timer () {}
Timer(const std::function<void(void)> &f) : funct (f) {}
Timer(const std::function<void(void)> &f,
const unsigned long &i,
const long repeat = Timer::Infinite) : funct (f),
interval (std::chrono::milliseconds(i)), CallNumber (repeat) {}
void Start (bool Async = true)
{
if (IsAlive ())
return;
Alive = true;
repeat_count = CallNumber;
if (Async)
Thread = std::thread (ThreadFunc,this);
else
this->ThreadFunc ();
}
void Stop ()
{
Alive = false;
Thread.join ();
}
void SetFunction (const std::function<void (void)> &f)
{
funct = f;
}
bool IsAlive () const
{
return Alive;
}
void RepeatCount (const long r)
{
if (Alive)
return;
CallNumber = r;
}
long GetLeftCount () const
{
return repeat_count;
}
long RepeatCount () const
{
return CallNumber;
}
void SetInterval (const unsigned long &i)
{
if (Alive)
return;
interval = std::chrono::milliseconds(i);
}
unsigned long Interval () const
{
return interval.count();
}
const std::function<void(void)> &Function () const
{
return funct;
}
};
#endif
Thank you very much.
error: 'thread' in namespace 'std' does not name a type
Whichever compiler you're using (looks like Visual C++) doesn't support std::thread (which is part of C++11).
I have a function accept multiple arguments.
#include <iostream>
#include <cstdarg>
#include <vector>
using namespace std;
template<typename... Values>
void doSomething(size_t input, Values... inputs)
{
size_t len = sizeof...(Values) + 1;
size_t vals[] = {input, inputs...};
vector<size_t> n(len);
std::copy( vals, vals+len, n.data() );
for(size_t i=0; i<len; i++) cout<<n[i]<<endl;
//Do something with n vector
}
It works fine when I call this function by:
size_t a(1), b(2), c(3);
doSomething(a,b,c);
However, it will have a problem when I call this function by:
doSomething(1,2,3);
It will give out warning message:
warning: narrowing conversion of ‘inputs#0’ from ‘int’ to ‘size_t {aka long unsigned int}’ inside { } [-Wnarrowing]
size_t vals[] = {inputs...};
I do not like this warning message, is there a way to solve this problem? I would like the function to be able to accept either size_t or int. Thank you.
I try to upgrade some projects from Visual Studio 2010 to 2015. In 2010 everything works fine, but in 2015 I get compiler errors which I don't really understand.
I condensed the code into an SSCCE
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <ctime>
#include <cstdlib>
#include <string>
#include <sstream>
#define UNUSED(x) (void(x))
class ColumnDef
{
public:
};
class XMLColumnDef
{
public:
typedef std::pair<std::string, XMLColumnDef> pair;
typedef std::pair<std::string, XMLColumnDef *> ptr_pair;
public:
// Move constructor for moving the column into an container
// without destroying it. Note that the source is no longer valid after
// such a move.
XMLColumnDef(XMLColumnDef &oSource)
{
mColumn = oSource.mColumn;
oSource.mColumn = NULL;
}
XMLColumnDef(ColumnDef *pColumn)
{
mColumn = pColumn;
}
virtual ~XMLColumnDef(void)
{
delete mColumn;
}
private:
ColumnDef *mColumn;
};
class XMLNodeObserver
{
public:
typedef std::map<std::string, XMLNodeObserver *> map;
typedef std::pair<std::string, XMLNodeObserver *> pair;
typedef std::map<std::string, XMLColumnDef> row_def;
public:
XMLNodeObserver(void) {}
virtual ~XMLNodeObserver(void) {};
void addObserver(XMLNodeObserver::map &oNodeObserver, std::string const &oPath, XMLNodeObserver *oObserver = NULL)
{
UNUSED(oNodeObserver);
UNUSED(oPath);
UNUSED(oObserver);
}
void addColumnDef(XMLNodeObserver::map &oNodeObserver, std::string const &oPath, ColumnDef *oColumn, XMLNodeObserver *oObserver = NULL)
{
if (oObserver == NULL)
oObserver = this;
addObserver(oNodeObserver, oPath, oObserver);
XMLColumnDef::pair pr = std::make_pair(oPath, XMLColumnDef(oColumn));
if (oObserver->mColumnDefs.find(oPath) != oObserver->mColumnDefs.end())
{
// If a node already exists, we report an internal error, because this indicates a program bug and should be fixed.
std::cerr << "INTERNAL ERROR: Duplicate rowdef key in XML node observer: " << oPath << std::endl;
}
oObserver->mColumnDefs.insert(pr);
}
private:
row_def mColumnDefs;
bool mDebugMode;
};
int main()
{
XMLNodeObserver o;
XMLNodeObserver::map om;
o.addColumnDef(om, "/testpath", new ColumnDef());
std::cout << "\nDone! Press any key..." << std::endl;
std::cin.ignore();
return 0;
}
The error I get in this line:
oObserver->mColumnDefs.insert(pr);
The error I get is this:
junk.cpp(104): error C2664: 'void std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>>::insert(std::initializer_list<std::pair<const _Kty,_Ty>>)': cannot convert argument 1 from 'XMLColumnDef::pair' to 'std::pair<const _Kty,_Ty> &&'
with
[
_Kty=std::string,
_Ty=XMLColumnDef,
_Pr=std::less<std::string>,
_Alloc=std::allocator<std::pair<const std::string,XMLColumnDef>>
]
and
[
_Kty=std::string,
_Ty=XMLColumnDef
]
junk.cpp(104): note: Reason: cannot convert from 'XMLColumnDef::pair' to 'std::pair<const _Kty,_Ty>'
with
[
_Kty=std::string,
_Ty=XMLColumnDef
]
junk.cpp(104): note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
It looks as if Visual Studio 2015 doesn't like it that the parameter oPath is const & but that shouldn't matter as it should be assigned to the pair member.
I also removed the typedefs and tried to compile it with the long names, but that doesn't seem to be the problem (and shouldn't anyway) because I get the same error.
Like:
std::pair<std::string, XMLColumnDef> pr = std::pair<std::string, XMLColumnDef>(oPath, XMLColumnDef(oColumn));
Pairs in maps are of type pair<const key,value> and not pair<key,value>. Try using the MyMapType::value_type typedef instead. You get it for free!
example:
typedef std::map<std::string, XMLNodeObserver *> MyMapType;
typedef MyMapType::value_type MyPairType;
My compiler is the latest VC++ 2013 preview. (Updated!)
#include <new>
struct A
{
A(int)
{}
};
void f(void (*fn)(void*))
{
A a(0);
fn(&a);
}
int main()
{
int n = 0;
auto fn = [&](void* p)
{
//
// error C2664: 'void f(void (__cdecl *)(void *))' :
// cannot convert parameter 1 from
// 'main::<lambda_b20f735b061d78dbb0f2f653ecbb482f>'
// to 'void (__cdecl *)(void *)'
//
new (p) A(n);
};
f(fn);
}
Why is this usage not allowed?
Is this behavior defined by the standard? If yes, what's the rationale?
void f(void (*fn)(void*))
takes a function pointer, not a lambda.
auto fn = [&](void* p)
is a lambda, and cannot be reduced to a function pointer because it involves a capture.
void f(std::function<void(void*)> fn)
will work. http://ideone.com/E7vvyW
#include <functional>
struct A
{
A(int)
{}
};
void f(std::function<void(void*)> fn)
{
A a(0);
fn(&a);
}
int main()
{
int n = 0;
auto fn = [&](void* p)
{
//
// error C2664: 'void f(void (__cdecl *)(void *))' :
// cannot convert parameter 1 from
// 'main::<lambda_b20f735b061d78dbb0f2f653ecbb482f>'
// to 'void (__cdecl *)(void *)'
//
new (p) A(n);
};
f(fn);
}