Cannot pass function as argument to std::thread when class is defined as template.
compiler: GCC 4.8.2
language: C++11
code:
//---------test.h-----------------------
#ifndef TEST_H
#define TEST_H
#include <iostream>
#include <thread>
using namespace std;
template <class T>
class test
{
public:
test();
void thr(T n);
void testThread();
};
#endif // TEST_H
//---------test.cpp-----------------------
#include "test.h"
template <class T>
test<T>::test()
{
}
template <class T>
void test<T>::thr(T n)
{
cout << n << endl;
}
template <class T>
void test<T>::testThread()
{
T n = 8;
thread t(thr, n);
t.join();
}
//---------main.cpp-----------------------
#include <iostream>
using namespace std;
#include "test.h"
#include "test.cpp"
int main()
{
test<double> tt;
tt.testThread();
return 0;
}
compiler error:
In file included from ../std_threads/main.cpp:5:0:
../std_threads/test.cpp: In instantiation of 'void test<T>::testThread() [with T = double]':
../std_threads/main.cpp:10:19: required from here
../std_threads/test.cpp:19:20: error: no matching function for call to 'std::thread::thread(<unresolved overloaded function type>, double&)'
thread t(thr, n);
^
../std_threads/test.cpp:19:20: note: candidates are:
In file included from ../std_threads/test.h:4:0,
from ../std_threads/main.cpp:4:
/usr/include/c++/4.8.2/thread:133:7: note: std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (test<double>::*)(double); _Args = {double&}]
thread(_Callable&& __f, _Args&&... __args)
^
/usr/include/c++/4.8.2/thread:133:7: note: no known conversion for argument 1 from '<unresolved overloaded function type>' to 'void (test<double>::*&&)(double)'
/usr/include/c++/4.8.2/thread:128:5: note: std::thread::thread(std::thread&&)
thread(thread&& __t) noexcept
^
/usr/include/c++/4.8.2/thread:128:5: note: candidate expects 1 argument, 2 provided
/usr/include/c++/4.8.2/thread:122:5: note: std::thread::thread()
thread() noexcept = default;
^
/usr/include/c++/4.8.2/thread:122:5: note: candidate expects 0 arguments, 2 provided
make: *** [main.o] Error 1
20:48:35: The process "/usr/bin/make" exited with code 2.
Error while building/deploying project std_threads (kit: Desktop)
When executing step 'Make'
You need to fully specify the member function name and pass an argument for the implicit first parameter of the non-static member function:
thread t(&test<T>::thr, this, n);
See std::thread of a member function.
Two problems:
to get a pointer to a member function, you need to use & and qualify the function name with the class name. Member functions names don't convert to pointers in the same way as non-member function names.
member functions need an object to act on.
So in this case, you probably want
thread t(&test<T>::thr, this, n);
Related
I found the following class definition in the boost library 1.71.0 which is installed at /usr/include/boost in my case.
class BOOST_SYMBOL_VISIBLE seconds : public time_duration
{
public:
template <typename T>
explicit seconds(T const& s,
typename boost::enable_if<boost::is_integral<T>, void>::type* = BOOST_DATE_TIME_NULLPTR) :
time_duration(0,0, numeric_cast<sec_type>(s))
{}
};
The Above class definition can be found out at /usr/include/boost/date_time/posix_time/posix_time_duration.hpp
I am using following code-snippet where the class boost::posix_time::seconds is instantiated:
#include <boost/asio.hpp>
#include <boost/array.hpp>
#include <boost/format.hpp>
#include <boost/bind.hpp>
#include <boost/serialization/access.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/shared_array.hpp>
#include <boost/algorithm/string.hpp>
#include <chrono>
#include <vector>
#include <boost/date_time/posix_time/posix_time_duration.hpp>
int main()
{
boost::asio::io_service io_service;
boost::asio::ip::tcp::socket socket(io_service);
boost::asio::deadline_timer timer(io_service);
timer.expires_from_now(boost::posix_time::seconds(60.0))
return 0;
}
Let's say I save the above code-snippet with the file name boost.cpp. Then I compile boost.cpp using the command
g++ -I /usr/include/boost -pthread boost.cpp
However, I am getting the following error:
boost.cpp: In function ‘int main()’:
boost.cpp:19:59: error: no matching function for call to ‘boost::posix_time::seconds::seconds(double)’
19 | timer.expires_from_now(boost::posix_time::seconds(60.0))
| ^
In file included from /usr/include/boost/date_time/posix_time/posix_time_types.hpp:16,
from /usr/include/boost/asio/time_traits.hpp:23,
from /usr/include/boost/asio/detail/timer_queue_ptime.hpp:22,
from /usr/include/boost/asio/detail/deadline_timer_service.hpp:29,
from /usr/include/boost/asio/basic_deadline_timer.hpp:24,
from /usr/include/boost/asio.hpp:25,
from boost.cpp:1:
/usr/include/boost/date_time/posix_time/posix_time_duration.hpp:57:16: note: candidate: ‘template<class T> boost::posix_time::seconds::seconds(const T&, typename boost::enable_if<boost::is_integral<T>, void>::type*)’
57 | explicit seconds(T const& s,
| ^~~~~~~
/usr/include/boost/date_time/posix_time/posix_time_duration.hpp:57:16: note: template argument deduction/substitution failed:
/usr/include/boost/date_time/posix_time/posix_time_duration.hpp: In substitution of ‘template<class T> boost::posix_time::seconds::seconds(const T&, typename boost::enable_if<boost::is_integral<T>, void>::type*) [with T = double]’:
boost.cpp:19:59: required from here
/usr/include/boost/date_time/posix_time/posix_time_duration.hpp:57:16: error: no type named ‘type’ in ‘struct boost::enable_if<boost::is_integral<double>, void>’
/usr/include/boost/date_time/posix_time/posix_time_duration.hpp:53:30: note: candidate: ‘boost::posix_time::seconds::seconds(const boost::posix_time::seconds&)’
53 | class BOOST_SYMBOL_VISIBLE seconds : public time_duration
| ^~~~~~~
/usr/include/boost/date_time/posix_time/posix_time_duration.hpp:53:30: note: no known conversion for argument 1 from ‘double’ to ‘const boost::posix_time::seconds&’
/usr/include/boost/date_time/posix_time/posix_time_duration.hpp:53:30: note: candidate: ‘boost::posix_time::seconds::seconds(boost::posix_time::seconds&&)’
/usr/include/boost/date_time/posix_time/posix_time_duration.hpp:53:30: note: no known conversion for argument 1 from ‘double’ to ‘boost::posix_time::seconds&&’
What I can think of is the use of the line boost::posix_time::seconds(60.0) is not correct but I am not able to figure out what's the correct way to instantiate the posix_time::seconds class based on the above definitions. Do any of you have an idea about it?
That constructor takes an integral (whole) number. boost::posix_time::seconds(60) should work.
Reference
Can anyone help me with this errors. When i compile this simple program
#include<queue>
using namespace std;
template<typename Queue>
int qtest(Queue & queue,typename Queue::Type item)
{
return 0;
}
int main()
{
std::queue<int> q;
int t = qtest(q,3);
}
I get the errors like below
In function 'int main()':
error: no matching function for call to 'qtest(std::queue<int>&, int)'
note: candidate is:
note: template<class Queue> int qtest(Queue&, typename Queue::Type)
note: template argument deduction/substitution failed:
In substitution of 'template<class Queue> int qtest(Queue&, typename Queue::Type) [with
Queue = std::queue<int>]':
required from here
error: no type named 'Type' in 'class std::queue<int>'
warning: unused variable 't' [-Wunused-variable]
std::queue doesn't have a member type called Type. That's what the compiler is telling us. I'm guessing what you're looking for is std::queue<int>::value_type.
template<typename Queue>
int qtest(Queue & queue,typename Queue::value_type item)
{
return 0;
}
Reference: cppreference
The following test program reproduces compilation errors within the context of a larger program:
#include <algorithm>
#include <iostream>
#include <vector>
using std::for_each;
using std::vector;
using std::cout;
using std::endl;
template<typename T, typename C = vector<T>>
class display_container{
public:
display_container(const C& cr):this->cr(cr){this->();}
~display_container(){}
private:
constexpr void operator () (void){if(cr.empty()){cout << "NULL" << " ";} else{for_each(cr.begin(), cr.end(), [](const T& crt){cout << crt << " ";});}}
const C& cr;
};
int main (void){
int n = 5;
vector<int> vec(n, 0);
display_container d(vec);
cout << endl;
return 0;
}
The following is a log of the compiler errors:
g++ -ggdb -std=c++17 -Wall -Werror=pedantic -Wextra -c code.cpp
code.cpp: In constructor ‘display_container<T, C>::display_container(const C&)’:
code.cpp:12:40: error: expected identifier before ‘this’
display_container(const C& cr):this->cr(cr){this->();}
^~~~
code.cpp:12:40: error: expected ‘{’ before ‘this’
code.cpp: In function ‘int main()’:
code.cpp:23:28: error: class template argument deduction failed:
display_container d(vec);
^
code.cpp:23:28: error: no matching function for call to ‘display_container(std::vector<int>&)’
code.cpp:12:9: note: candidate: template<class T, class C> display_container(const C&)-> display_container<T, C>
display_container(const C& cr):this->cr(cr){this->();}
^~~~~~~~~~~~~~~~~
code.cpp:12:9: note: template argument deduction/substitution failed:
code.cpp:23:28: note: couldn't deduce template parameter ‘T’
display_container d(vec);
^
code.cpp:10:7: note: candidate: template<class T, class C> display_container(display_container<T, C>)-> display_container<T, C>
class display_container{
^~~~~~~~~~~~~~~~~
code.cpp:10:7: note: template argument deduction/substitution failed:
code.cpp:23:28: note: ‘std::vector<int>’ is not derived from ‘display_container<T, C>’
display_container d(vec);
^
make: *** [makefile:20: code.o] Error 1
I presume that the remaining errors trickle down from the first error related to the inline constructor definition for the display_container template class.
Any suggestions on what is wrong with the code related to inline constructor definition?
TIA
The compiler can not fetch the template type of vector yet:
#include <algorithm>
#include <iostream>
#include <vector>
using std::for_each;
using std::vector;
using std::cout;
using std::endl;
template<typename T, typename C = vector<T>>
class display_container{
public:
display_container(const C& cr): cr(cr) { (*this)(); }
~display_container(){}
private:
constexpr void operator () (void){if(cr.empty()){cout << "NULL" << " ";} else{for_each(cr.begin(), cr.end(), [](const T& crt){cout << crt << " ";});}}
const C& cr;
};
int main (void){
int n = 5;
vector<int> vec(n, 0);
display_container<int> d(vec);
cout << endl;
return 0;
}
You couldn't (and don't need) qualify data members in member initializer list by this, they're expected to be the identifier. The correct syntax should be
display_container(const C& cr):cr(cr){(*this)();}
You should dereference on this and then call operator() on it (as showed abolve), or you can call operator() explicitly like this->operator()(); (which looks ugly).
You should specify the template argument for display_container.
display_container<int> d(vec);
LIVE
#include <string.h>
#include <vector>
#include <algorithm>
#include <boost/filesystem.hpp>
#include <boost/foreach.hpp>
#include <boost/regex.hpp>
struct FileSorter{
virtual ~FileSorter(){}
virtual bool operator()(const boost::filesystem::path& p1, const boost::filesystem::path& p2) const =0;
};
struct SortByName : public FileSorter{
SortByName(bool ascending=true):ascending_order(ascending)
{
}
virtual bool operator()(const boost::filesystem::path& p1, const boost::filesystem::path& p2) const {
if(ascending_order)
return p1.stem().string() < p2.stem().string();
else
return p1.stem().string() > p2.stem().string();
}
protected:
bool ascending_order;
};
class FilesList : public std::vector<boost::filesystem::path> {
public:
FilesList(const std::string& dir, const std::string& f_regex, const FileSorter& fileSorter=SortByName()) {
boost::regex e(f_regex, boost::regex::perl);
boost::filesystem::path path(dir);
if(!boost::filesystem::is_directory(path)) {
throw std::runtime_error(path.string()+std::string(" is not a directory\n"));
}
for(boost::filesystem::directory_iterator file(path), f_end; file!= f_end; ++file){
if(boost::regex_match(file->path().filename().string(), e))
this->push_back(file->path());
}
std::sort(this->begin(), this->end(), fileSorter);
}
};
I defined a class FileList which do perform create a list of files which meet the regular expression(f_regex argument).
To sort the list, an instance of SortBy*** struct(inherited from FileSorter) can be passed.
The problem is std::sort function cannot be compiled with the code above showing the following error message.
/usr/include/c++/4.8/bits/stl_algo.h:5483:5: error: cannot allocate an object of abstract type ‘FileSorter’
I don't understand this behavior. In my narrow knowledge, struct equipped with operator () is called functor and it is a good way to deal with a function as an object.
And as all we know, instance of child class can be referred by a reference of parent class.
But the above example is saying differently.
What should I change to make the code work?
If I have wrong concepts about c++, please don't hesitate to scold me.
Full compile error messages are here.
$ make
Scanning dependencies of target cpp_factory
[ 11%] Building CXX object CMakeFiles/cpp_factory.dir/libraries/src/FileLister.cpp.o
In file included from /home/ub1404/Application/cpp_factory/libraries/src/FileLister.cpp:5:0:
/home/ub1404/Application/cpp_factory/libraries/include/cpp_factory/files/FileLister.h: In constructor ‘FilesList::FilesList(const string&, const string&, const FileSorter&)’:
/home/ub1404/Application/cpp_factory/libraries/include/cpp_factory/files/FileLister.h:109:57: error: no matching function for call to ‘sort(std::vector<boost::filesystem::path>::iterator, std::vector<boost::filesystem::path>::iterator, const FileSorter&)’
std::sort(this->begin(), this->end(), fileSorter);
^
/home/ub1404/Application/cpp_factory/libraries/include/cpp_factory/files/FileLister.h:109:57: note: candidates are:
In file included from /usr/include/c++/4.8/algorithm:62:0,
from /home/ub1404/Application/cpp_factory/libraries/include/cpp_factory/files/FileLister.h:11,
from /home/ub1404/Application/cpp_factory/libraries/src/FileLister.cpp:5:
/usr/include/c++/4.8/bits/stl_algo.h:5447:5: note: template<class _RAIter> void std::sort(_RAIter, _RAIter)
sort(_RandomAccessIterator __first, _RandomAccessIterator __last)
^
/usr/include/c++/4.8/bits/stl_algo.h:5447:5: note: template argument deduction/substitution failed:
In file included from /home/ub1404/Application/cpp_factory/libraries/src/FileLister.cpp:5:0:
/home/ub1404/Application/cpp_factory/libraries/include/cpp_factory/files/FileLister.h:109:57: note: candidate expects 2 arguments, 3 provided
std::sort(this->begin(), this->end(), fileSorter);
^
In file included from /usr/include/c++/4.8/algorithm:62:0,
from /home/ub1404/Application/cpp_factory/libraries/include/cpp_factory/files/FileLister.h:11,
from /home/ub1404/Application/cpp_factory/libraries/src/FileLister.cpp:5:
/usr/include/c++/4.8/bits/stl_algo.h:5483:5: note: template<class _RAIter, class _Compare> void std::sort(_RAIter, _RAIter, _Compare)
sort(_RandomAccessIterator __first, _RandomAccessIterator __last,
^
/usr/include/c++/4.8/bits/stl_algo.h:5483:5: note: template argument deduction/substitution failed:
/usr/include/c++/4.8/bits/stl_algo.h: In substitution of ‘template<class _RAIter, class _Compare> void std::sort(_RAIter, _RAIter, _Compare) [with _RAIter = __gnu_cxx::__normal_iterator<boost::filesystem::path*, std::vector<boost::filesystem::path> >; _Compare = FileSorter]’:
/home/ub1404/Application/cpp_factory/libraries/include/cpp_factory/files/FileLister.h:109:57: required from here
/usr/include/c++/4.8/bits/stl_algo.h:5483:5: error: cannot allocate an object of abstract type ‘FileSorter’
In file included from /home/ub1404/Application/cpp_factory/libraries/src/FileLister.cpp:5:0:
/home/ub1404/Application/cpp_factory/libraries/include/cpp_factory/files/FileLister.h:49:8: note: because the following virtual functions are pure within ‘FileSorter’:
struct FileSorter{
^
/home/ub1404/Application/cpp_factory/libraries/include/cpp_factory/files/FileLister.h:51:18: note: virtual bool FileSorter::operator()(const boost::filesystem::path&, const boost::filesystem::path&) const
virtual bool operator()(const boost::filesystem::path& p1, const boost::filesystem::path& p2) const =0;
^
make[2]: *** [CMakeFiles/cpp_factory.dir/libraries/src/FileLister.cpp.o] Error 1
make[1]: *** [CMakeFiles/cpp_factory.dir/all] Error 2
make: *** [all] Error 2
If you look at the signature, std::sort takes its comparison object by value:
template< class RandomIt, class Compare >
void sort( RandomIt first, RandomIt last, Compare comp );
So when you write:
std::sort(this->begin(), this->end(), fileSorter);
your object gets sliced, and you end up trying to instantiate a function which takes an abstract class by value, hence all the errors you end up with.
What you need to do is ensure that even though sort takes its comparison by value, you pass yours in by reference. Thankfully, there's an app for that! Just use std::ref:
std::sort(this->begin(), this->end(), std::ref(fileSorter));
That said, do you really need a polymorphic comparator? If you're just passing in different comparison function objects into the FilesList constructor, you should prefer to just make it a function template:
template <class Sorter>
FilesList(const std::string& dir, const std::string& f_regex, Sorter fileSorter) {
// ...
std::sort(begin(), end(), fileSorter); // now copying is fine
}
That way, you can just directly forward in what the user passes and avoid virtual dispatch.
Your FileSorter argument is defaulted to a SortByExtension object rather than a SortByName object. As you haven't included the source of SortByExtension, I would start by checking that function signature of SortByExtension's function call operator is
bool SortByExtension::operator()(const path&, const path&) const
If there are any differences between the base class and derived class function signatures, the derived class function won't override the base class one, and the derived class will be treated as an abstract class.
I am working on a code and unable to use sort() method from inside a class.
class MyClass {
struct MyStruct {
...
} MyStructArr[10];
void fun() {
... // setting values of MyStructArr
sort(MyStructArr, MyStructArr + 10, cmp); // !ERROR!
}
int cmp(struct MyStruct a, struct MyStruct b) {
...
}
};
But same code is working without class
struct MyStruct {
...
} MyStructArr[10];
int main() {
... // setting values of MyStructArr
sort(MyStructArr, MyStructArr + 10, cmp);
return 0;
}
int cmp(struct MyStruct a, struct MyStruct b) {
...
}
I cannot understand why the sort(...) with comparison function is not working inside
the class.
Here is the error :
SuffixArray.cpp: In member function 'void SuffixArray_Entry::suffixArray()':
SuffixArray.cpp:31:43: error: no matching function for call to 'sort(SuffixArray_Entry::SuffixArray_entry [65536], SuffixArray_Entry::SuffixArray_entry*, <unresolved overloaded function type>)'
sort(L, L + N, SuffixArray_cmp);
^
SuffixArray.cpp:31:43: note: candidates are:
In file included from c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\algorithm:62:0,
from SuffixArray.cpp:3:
c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\bits\stl_algo.h:5461:5: note: template<class _RAIter> void std::sort(_RAIter, _RAIter)
sort(_RandomAccessIterator __first, _RandomAccessIterator __last)
^
c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\bits\stl_algo.h:5461:5: note: template argument deduction/substitution failed:
SuffixArray.cpp:31:43: note: candidate expects 2 arguments, 3 provided
sort(L, L + N, SuffixArray_cmp);
^
In file included from c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\algorithm:62:0,
from SuffixArray.cpp:3:
c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\bits\stl_algo.h:5497:5: note: void std::sort(_RAIter, _RAIter, _Compare) [with _RAIter = SuffixArray_Entry::SuffixArray_entry*; _Compare = int (SuffixArray_Entry::*)(SuffixArray_Entry::SuffixArray_entry, SuffixArray_Entry::SuffixArray_entry)]
sort(_RandomAccessIterator __first, _RandomAccessIterator __last,
^
c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\bits\stl_algo.h:5497:5: note: no known conversion for argument 3 from '<unresolved overloaded function type>' to 'int (SuffixArray_Entry::*)(SuffixArray_Entry::SuffixArray_entry, SuffixArray_Entry::SuffixArray_entry)'
make.exe[2]: *** [build/Debug/MinGW-Windows/SuffixArray.o] Error 1
make.exe[2]: Leaving directory `/c/Users/Afzalex/Documents/NetBeansProjects/TestingStore/CPPStoreRoom'
make.exe[1]: *** [.build-conf] Error 2
make.exe[1]: Leaving directory `/c/Users/Afzalex/Documents/NetBeansProjects/TestingStore/CPPStoreRoom'
make.exe": *** [.build-impl] Error 2
It is error stack trace for my original program. I am using Netbeans with MinGW
Declare member function cmp as a static member function.
Take into account that it would be much better if the parameters of the function would be references.
The other way is to define a functional object inside the class. For example
class MyClass {
struct MyStruct {
...
} MyStructArr[10];
struct cmp
{
bool operator ()( const struct MyStruct &a, const struct MyStruct &b ) const
{
//....
}
};
void fun() {
... // setting values of MyStructArr
sort(MyStructArr, MyStructArr + 10, cmp());
}
...
Also you could define operator < for structure MyStruct. In this case you could call std::sort without a predicate.
sort will have some code that looks like this inside:
template <typename Iter, typename Cmp>
void sort(Iter begin, Iter end, Cmp cmp)
{
// other code
if (cmp(a, b)) { // <-- !!!
// Do something
} else {
// Do something else
}
}
Note that to call cmp as you originally posted it, you would need something like:
myClassInstance->cmp(a, b)
but sort doesn't have a MyClass to call cmp on, it only has the things it actually wants to compare.
You can either make your cmp not depend on MyClass (by making it a nonmember function or by making it static) or you can bind an instance of MyClass to it by using a lambda or std::bind or similar.