Executing a member function of a class - c++

I am trying to experiment the C++11 threads in a way that it accepts a member function of a class as a parameter into the thread constructor as shown in the first code snippet below on line 20 that is marked . The class definition is given in the 2nd code snippet. When this code is compiled, I am getting a bunch of errors shown in the 3rd snippet. Can anyone tell me what I am doing wrong? Thanks.
SNIPPET 1: Thread initialization (main_app.cpp)
#include <thread>
#include "ServiceRegistrar.hpp"
#define SERVER_TYPE 100065
#define SERVER_INST_LOWER 1
#define SERVER_INST_UPPER 2
#define TIMEOUT 500000
int main()
{
ServiceRegistrar sr1(SERVER_TYPE, TIMEOUT, SERVER_INST_LOWER, SERVER_INST_LOWER);
/*LINE 20 is the following*/
std::thread t(&ServiceRegistrar::subscribe2TopologyServer, sr1);
t.join();
sr1.publishForSRs();
}
SNIPPET 2: Class definition
class ServiceRegistrar
{
public:
ServiceRegistrar(int serverType, int serverTimeOut, int serverInstanceLower, int serverInstanceUpper)
: mServerType(serverType),
mServerTimeOut(serverTimeOut),
mServerInstanceLower(serverInstanceLower),
mServerInstanceUpper(serverInstanceUpper)
{ }
void subscribe2TopologyServer();
void publishForSRs();
void publishForServices();
private:
int mServerType;
int mServerTimeOut;
int mServerInstanceLower;
int mServerInstanceUpper;
};
SNIPPET 3: Compilation output
$ g++ -g -c -Wall -std=c++11 main_app.cpp -pthread
In file included from /usr/include/c++/4.7/ratio:38:0,
from /usr/include/c++/4.7/chrono:38,
from /usr/include/c++/4.7/thread:38,
from main_app.cpp:8:
/usr/include/c++/4.7/type_traits: In instantiation of ‘struct std::_Result_of_impl<false, false, std::_Mem_fn<void (ServiceRegistrar::*)()>, ServiceRegistrar>’:
/usr/include/c++/4.7/type_traits:1857:12: required from ‘class std::result_of<std::_Mem_fn<void (ServiceRegistrar::*)()>(ServiceRegistrar)>’
/usr/include/c++/4.7/functional:1563:61: required from ‘struct std::_Bind_simple<std::_Mem_fn<void (ServiceRegistrar::*)()>(ServiceRegistrar)>’
/usr/include/c++/4.7/thread:133:9: required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (ServiceRegistrar::*)(); _Args = {ServiceRegistrar&}]’
main_app.cpp:20:64: required from here
/usr/include/c++/4.7/type_traits:1834:9: error: no match for call to ‘ (std::_Mem_fn<void (ServiceRegistrar::*)()>) (ServiceRegistrar)’

Apparently it's a gcc 4.7 bug...use
std::thread t(&ServiceRegistrar::subscribe2TopologyServer, &sr1);
instead.
EDIT: actually, you probably don't want to be copying sr1 to the thread-local-storage of t, so this is better anyway.

Try:
std::thread t(std::bind(&ServiceRegistrar::subscribe2TopologyServer, sr1));
Hope it helps.

Related

Error of threads in C++ "static assertion failed"

I made a quick summary of a project i have,
in which I have two threads that should be able to read and write on a common variable (protected by a mutex in the real project.
I don't understand this error
the two threads are in theory launched by a main thread
this main thread is a function of the object whose role is to manage the sub threads of this object.
I d'ont know if this is possible
main.cpp
#include <thread>
#include "Object.h"
using namespace std;
int main(){
Object tmp;
tmp.ChangeSetting(42);
thread mainthread(&Object::MainTread, &tmp);
mainthread.join();
}
Object.h
#ifndef SRC_OBJECT_H_
#define SRC_OBJECT_H_
#include <thread>
#include <iostream>
using namespace std;
class Object {
private:
int stupidvalue;
void subThread1();
void subThread2();
public:
void MainTread();
void ChangeSetting(int psvalue);
Object();
virtual ~Object();
};
#endif /* SRC_OBJECT_H_ */
Object.cpp
#include "Object.h"
void Object::subThread1(){
cout << "subthread1";
}
void Object::subThread2(){
cout << "subthread2";
}
void Object::MainTread(){
thread tmp1(subThread1);
thread tmp2(subThread2);
tmp1.join();
tmp2.join();
}
Object::Object() {
stupidvalue = 0;
}
void Object::ChangeSetting(int psvalue){
stupidvalue = psvalue;
}
Object::~Object() {
}
and my error
Info: Internal Builder is used for build
g++ -O0 -g3 -Wall -c -fmessage-length=0 -o "src\\main.o" "..\\src\\main.cpp"
g++ -O0 -g3 -Wall -c -fmessage-length=0 -o "src\\Object.o" "..\\src\\Object.cpp"
In file included from ..\src\Object.h:5,
from ..\src\Object.cpp:2:
C:/msys64/mingw32/include/c++/10.2.0/thread: In instantiation of 'std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (Object::*)(); _Args = {}; <template-parameter-1-3> = void]':
..\src\Object.cpp:13:24: required from here
C:/msys64/mingw32/include/c++/10.2.0/thread:136:44: error: static assertion failed: std::thread arguments must be invocable after conversion to rvalues
136 | typename decay<_Args>::type...>::value,
| ^~~~~
10:26:25 Build Failed. 1 errors, 0 warnings. (took 1s.304ms)
I read that it could be a typing error, but there is no parameter.
subThread1 and subThread2 are also member functions. You need to use pointer-to-member-function syntax like you did in main()
void Object::MainTread(){
thread tmp1(&Object::subThread1, this);
thread tmp2(&Object::subThread2, this);
tmp1.join();
tmp2.join();
}
Or use lambdas like the other answer suggests.
You are passing non-static method without object itself:
thread tmp1(subThread1); //error: subThread() cannot be invoked without object
You could make a lambda:
// passing this to lambda ok solong the object itself outlives the lambda ...
// in your case ok because joining in place.
thread tmp1([this]() { this->subThread(); });
Otherwise if thread could outlive the object, you would normally make a shared pointer (this way the object would leave through the shared_pointer at least as long as thread itself):
thread tmp1([self=this->shared_from_this()]() { self->subThread(); });
For this to work, Object would need to inherit from std::enable_shared_from_this<Object>:
class Object : public std::enable_shared_from_this<Object> {...}

Trouble definining hash function for custom type in unordered_multimap on MacOS

So I want to use a custom type (here, SWrapper) as the key type for an unordered_multimap. I've defined a hash class, derived from the standard hashing function for strings, and included the hashing class in the type of the multimap. Some code that reproduces the error is displayed below. This compiles on Arch Linux with both g++ and clang++, but on MacOS with clang++, I get errors:
#include <unordered_map>
#include <functional>
#include <string>
class SWrapper {
public:
SWrapper() {
(*this).name = "";
}
SWrapper(std::string name) {
(*this).name = name;
}
bool operator==(SWrapper const& other) {
return (*this).name == other.name;
}
std::string name;
};
class SWrapperHasher {
size_t operator()(SWrapper const& sw) const {
return std::hash<std::string>()(sw.name);
}
};
int main(int argc, char* argv[]) {
auto mm = std::unordered_multimap<SWrapper, int, SWrapperHasher>();
return 0;
}
Running g++ -std=c++11 -Wall -Wpedantic -Wextra hash_map_test.cpp -o hash_map_test on Arch Linux (or clang++) compiles the code with no errors. However, on MacOS, using the same command, I get the following error message:
In file included from hash_map_test.cpp:1:
In file included from /Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/unordered_map:408:
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/__hash_table:868:5: error:
static_assert failed due to requirement 'integral_constant<bool, false>::value' "the
specified hash does not meet the Hash requirements"
static_assert(__check_hash_requirements<_Key, _Hash>::value,
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/__hash_table:883:1: note: in
instantiation of template class
'std::__1::__enforce_unordered_container_requirements<SWrapper, SWrapperHasher,
std::__1::equal_to<SWrapper> >' requested here
typename __enforce_unordered_container_requirements<_Key, _Hash, _Equal>::type
^
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/unordered_map:1682:26: note: while
substituting explicitly-specified template arguments into function template
'__diagnose_unordered_container_requirements'
static_assert(sizeof(__diagnose_unordered_container_requirements<_Key, _Hash, _Pred>(...
^
hash_map_test.cpp:29:15: note: in instantiation of template class
'std::__1::unordered_multimap<SWrapper, int, SWrapperHasher, std::__1::equal_to<SWrapper>,
std::__1::allocator<std::__1::pair<const SWrapper, int> > >' requested here
auto mm = std::unordered_multimap<SWrapper, int, SWrapperHasher>();
^
1 error generated.
I've tried interpreting the error message, but I'm really at a loss of what to make of it. If anyone has any suggestions as to what's going on here, and how I can work around this on MacOS, it'd be greatly appreciated!
The compiler's complaint unfortunately does not say which requirement was not met. In this case, the problem comes from SWrapperHasher::operator() being private. Marking that public (changing class to struct does this implicitly) makes the unordered map legal.

Compilation error: `error: definition of implicitly-declared`

I am trying to create a class which calls one of it's functions when created, but I am getting the following error when compiling:
g++ -std=c++11 -Wall -Wextra -Werror -pedantic-errors -DNDEBUG -c src/PuzzleSolution.cpp
src/PuzzleSolution.cpp:7:32: error: definition of implicitly-declared 'PuzzleSolution::PuzzleSolution()'
PuzzleSolution::PuzzleSolution()
^
src/PuzzleSolution.cpp:12:6: error: prototype for 'void PuzzleSolution::addRow()' does not match any in class 'PuzzleSolution'
void PuzzleSolution::addRow()
^
src/PuzzleSolution.h:19:10: error: candidate is: void PuzzleSolution::addRow(std::vector<unsigned int>&)
explicit PuzzleSolution();
^
src/PuzzleSolution.cpp:17:48: error: no 'void PuzzleSolution::addElement(unsigned int)' member function declared in class 'PuzzleSolution'
void PuzzleSolution::addElement(unsigned int id)
^
make: *** [PuzzleSolution.o] Error 1
Here is the header:
#include <vector>
using namespace std;
class PuzzleSolution {
private:
vector<vector<unsigned int>> sol;
public:
explicit PuzzleSolution();
void addRow();
};
Here is the cpp file:
#include "PuzzleSolution.h"
PuzzleSolution::PuzzleSolution()
{
addRow();
}
void PuzzleSolution::addRow()
{
this->sol.emplace_back();
}
What am I doing wrong?
The code as it is has no error. It compiles with GCC 4.8.2
Be sure that your header file is indeed what you have linked to. Most likely the header being included is different than the one you have actually posted here.
Side Note: Generally it is considered as a bad practice to put using namespace std; in a header file.
Found the issue:
There was a file in the src folder called PuzzleSolution.h.gch
#Quatin and #StoryTeller helped me to understand that this is a pre-compiled header, which the compiler kept using.
Once deleted, the project compiled and executed

Pass a refrence for thread constructor to bind it to function fails?

I have a void fun(vector<int> & v) and I want to pass a vector to it when instantiating a thread thread t(fun, v);. In C++14 clang 4 compilation fails, in MSVC it runs passing a copy to function.
#include <thread>
#include <vector>
#include <iostream>
using namespace std;
void fun(vector<int> & v) {
v.push_back(13);
}
int main(){
vector<int> v;
thread t(fun, v);
t.join();
cout << v.size();
}
example of gcc 5.4.0 error:
In file included from /usr/include/c++/5/thread:39:0,
from source_file.cpp:1: /usr/include/c++/5/functional: In instantiation of ‘struct
std::_Bind_simple))(std::vector&)>’:
/usr/include/c++/5/thread:137:59: required from
‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void
(&)(std::vector&); _Args = {std::vector
&}]’ source_file.cpp:12:21: required from here /usr/include/c++/5/functional:1505:61: error: no type named ‘type’ in
‘class std::result_of))(std::vector&)>’
typedef typename result_of<_Callable(_Args...)>::type result_type;
^ /usr/include/c++/5/functional:1526:9: error: no type named ‘type’ in
‘class std::result_of))(std::vector&)>’
_M_invoke(_Index_tuple<_Indices...>)
So 1) what is c++ standard stand on this issue; 2) is there a way around it (not passing a pointer and not +1 extra lambda expression as wrapper)?
As pointed out by Galik in the comment, all you need is std::ref():
thread t(fun, std::ref(v));
Why ?
This is because your function fun() expects a reference to an lvalue. However when you construct your thread(), a copy of your arguments will be passed in the new thread. Unfortunately, the compiler will not be able to instantiate the templates behind the scene with a reference to a temporary copy in this case.
Putting the std::ref(), will cause the reference to the original to be used, and make the whole thing to work as expected.

std::sort with local type Compare

The following example
// file mysort.cc
#include <string>
#include <vector>
#include <algorithm>
#include <string.h>
void mysort (const char**tab, unsigned size) {
std::vector<int> vecix;
vecix.resize(size);
struct CompareIndex {
const char**t;
CompareIndex(const char**p) : t(p) {};
bool operator() (int l, int r) {
return strcmp(t[l], t[r])<0;
}
};
CompareIndex compix(tab);
for (unsigned ix=0; ix<size; ix++) vecix[ix] = ix;
std::stable_sort(vecix.begin(), vecix.end(), compix);
std::vector<const char*> vecstr;
vecstr.resize(size);
for (unsigned ix=0; ix<size; ix++) vecstr[ix] = tab[vecix[ix]];
for (unsigned ix=0; ix<size; ix++) tab[ix] = vecstr[ix];
}
fails to compile (using GCC 4.8.2 on Debian/Sid/x86-64 in C++03 standard)
mysort.cc: In function 'void mysort(const char**, unsigned int)':
mysort.cc:19:58: error: no matching function for call to
'stable_sort(std::vector<int>::iterator,
std::vector<int>::iterator,
mysort(const char**, unsigned int)::CompareIndex&)'
std::stable_sort(vecix.begin(), vecix.end(), compix);
^
In file included from /usr/include/c++/4.8/algorithm:62:0,
from mysort.cc:4:
/usr/include/c++/4.8/bits/stl_algo.h:5682:5: note:
template<class _RAIter, class _Compare>
void std::stable_sort(_RAIter, _RAIter, _Compare)
stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last,
^
/usr/include/c++/4.8/bits/stl_algo.h:5682:5: note:
template argument deduction/substitution failed:
mysort.cc: In substitution of 'template<class _RAIter, class _Compare>
void std::stable_sort(_RAIter, _RAIter, _Compare)
[with _RAIter = __gnu_cxx::__normal_iterator<int*, std::vector<int> >;
_Compare = mysort(const char**, unsigned int)::CompareIndex]':
mysort.cc:19:58: required from here
mysort.cc:19:58: error: template argument for
'template<class _RAIter, class _Compare>
void std::stable_sort(_RAIter, _RAIter, _Compare)'
uses local type 'mysort(const char**, unsigned int)::CompareIndex'
std::stable_sort(vecix.begin(), vecix.end(), compix);
^
mysort.cc:19:58: error: trying to instantiate
'template<class _RAIter, class _Compare>
void std::stable_sort(_RAIter, _RAIter, _Compare)'
The above was compiled with GCC 4.8 using
g++ -Wall -c mysort.cc
I am getting the same error with
g++ -std=c++03 -Wall -c mysort.cc
or with
g++ -std=c++98 -Wall -c mysort.cc
but no errors with
g++ -std=c++11 -c mysort.cc
given that my g++ -v is a gcc version 4.8.2 (Debian 4.8.2-12)
but with Clang/LLVM 3.4 compiling with
clang++ -Wall -c mysort.cc
I'm getting only a warning:
mysort.cc:19:7: warning: template argument uses local
type 'CompareIndex'
[-Wlocal-type-template-args]
std::stable_sort(vecix.begin(), vecix.end(), compix);
^~~
1 warning generated.
(and I still get only a warning not an error when passing -std=c++03 or -std=c++98 to clang++ but no warnings with clang++ -std=c++11)
so my question is: why the error by GCC and the warning by Clang? Is my code legal and without undefined behavior (w.r.t. the C++03 standard)? Should I make my CompareIndex a global struct in my compilation unit?
motivations
Of course, this is a silly way to sort an array of C strings.
The real code is a bit different. In fact, I am trying to use std::stable_sort in my MELT plugin (a domain specific language to extend and customize GCC). MELT is generating C++ code and has a copying garbage collector (so pointers are moved by the GC). Hence, I need to sort using an array of indexes: the compare function in fact calls a MELT closure (which could trigger the copying GC at arbitrary moment), so I need to sort by indexes (and not by raw pointers). I want to keep the C++ code generated by MELT conforming to the C++ standard (03 or 98) required to compile GCC.
work-around
Thanks to juanchopanza's answer I've solved the issue by moving the declaration of CompareIndex at global scope before mysort.
I just committed the svn revision 206748 of the MELT branch of GCC; its file gcc/melt/warmelt-base.melt contains now a multiple_sort_new MELT function (to replace multiple_sort when it is working well) using std::stable_sort, and a global Melt_Sort_Compare_Index class in the generated C++ code.
Using local types as template arguments is not allowed in C++03.
From ISO/IEC 14882, 14.3.1 Template type arguments [temp.arg.type]:
A local type, a type with no linkage, an unnamed type or a type
compounded from any of these types shall not be used as a
template-argument for a template type-parameter.
The example given is along these lines:
template <typename T> struct Foo {};
void foo()
{
struct Bar {};
Foo<Bar> b1; // error: local type used as template-argument
Foo<Bar*> x4; // error: pointer to local type used as template-argument
}
This restriction has been lifted in C++11.