thread not working for function with template arguments - c++

I am trying to implement multithreaded merge sort, but my attempt is fails to compile. Here is my code :
template <class RandomAccessIterator>
void merge_sort (RandomAccessIterator begin,RandomAccessIterator end)
{
int N = end - begin;
int N1,N2;
if (N == 1)
return;
RandomAccessIterator mid = begin + (end-begin)/2;
// merge_sort (begin,mid); // this is OK
// merge_sort (mid,end); // this is OK
thread t1 (merge_sort,begin,mid); // error
thread t2 (merge_sort,mid,end); // error
t1.join ();
t2.join ();
N1 = mid - begin;
N2 = end - mid;
merge (begin,N1,mid,N2);
}
Errors Messages from gcc (g++ -std=c++11 merge-multithread.cpp):
merge-multithread.cpp: In instantiation of ‘void merge_sort(RandomAccessIterator, RandomAccessIterator) [with RandomAccessIterator = int*]’:
merge-multithread.cpp:76:25: required from here
merge-multithread.cpp:60:33: error: no matching function for call to ‘std::thread::thread(<unresolved overloaded function type>, int*&, int*&)’
thread t1 (merge_sort,begin,mid);
^
In file included from merge-multithread.cpp:4:0:
/usr/include/c++/5.2.0/thread:133:7: note: candidate: template<class _Callable, class ... _Args> std::thread::thread(_Callable&&, _Args&& ...)
thread(_Callable&& __f, _Args&&... __args)
^
/usr/include/c++/5.2.0/thread:133:7: note: template argument deduction/substitution failed:
merge-multithread.cpp:60:33: note: couldn't deduce template parameter ‘_Callable’
thread t1 (merge_sort,begin,mid);
^
In file included from merge-multithread.cpp:4:0:
/usr/include/c++/5.2.0/thread:128:5: note: candidate: std::thread::thread(std::thread&&)
thread(thread&& __t) noexcept
^
/usr/include/c++/5.2.0/thread:128:5: note: candidate expects 1 argument, 3 provided
/usr/include/c++/5.2.0/thread:122:5: note: candidate: std::thread::thread()
thread() noexcept = default;

merge_sort itself is a function template; to get the address of one of the instantiated functions you need to specify all template arguments:
thread t1 (&merge_sort<RandomAccessIterator>,begin,mid);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
or use a static cast:
thread t1 (static_cast<void(*)(RandomAccessIterator,RandomAccessIterator)>(&merge_sort),begin,mid);
...or use a lambda expression and let the compiler automatically deduce the types of arguments:
thread t1 ([begin,mid]{merge_sort(begin, mid);});

Related

RcppParallel no matching function for call to 'transform'

I have a package posted on CRAN which uses multiple cores through the RcppParallel framework. It has the problem being installed on r-devel-linux-x86_64-fedora-clang and r-patched-solaris-x86. I get the following error messages (there are couple of similar messages related to std::transform so I present just one of them for brevity):
1.For the r-patched-solaris-x86:
ParallelFunctions.cpp: In member function ‘virtual void ParallelVectorExpStruct::operator()(std::size_t, std::size_t)’:
ParallelFunctions.cpp:134:27: error: no matching function for call to ‘transform(RcppParallel::RVector<double>::const_iterator, RcppParallel::RVector<double>::const_iterator, RcppParallel::RVector<double>::iterator, <unresolved overloaded function type>)’
::exp);
^
In file included from /opt/csw/include/c++/5.2.0/algorithm:62:0,
from /home/ripley/R/Lib32/Rcpp/include/RcppCommon.h:63,
from /home/ripley/R/Lib32/RcppArmadillo/include/RcppArmadilloForward.h:26,
from /home/ripley/R/Lib32/RcppArmadillo/include/RcppArmadillo.h:31,
from ParallelFunctions.h:4,
from ParallelFunctions.cpp:1:
/opt/csw/include/c++/5.2.0/bits/stl_algo.h:4164:5: note: candidate: template<class _IIter, class _OIter, class _UnaryOperation> _OIter std::transform(_IIter, _IIter, _OIter, _UnaryOperation)
transform(_InputIterator __first, _InputIterator __last,
^
/opt/csw/include/c++/5.2.0/bits/stl_algo.h:4164:5: note: template argument deduction/substitution failed:
ParallelFunctions.cpp:134:27: note: couldn't deduce template parameter ‘_UnaryOperation’
::exp);
^
In file included from /opt/csw/include/c++/5.2.0/algorithm:62:0,
from /home/ripley/R/Lib32/Rcpp/include/RcppCommon.h:63,
from /home/ripley/R/Lib32/RcppArmadillo/include/RcppArmadilloForward.h:26,
from /home/ripley/R/Lib32/RcppArmadillo/include/RcppArmadillo.h:31,
from ParallelFunctions.h:4,
from ParallelFunctions.cpp:1:
/opt/csw/include/c++/5.2.0/bits/stl_algo.h:4201:5: note: candidate: template<class _IIter1, class _IIter2, class _OIter, class _BinaryOperation> _OIter std::transform(_IIter1, _IIter1, _IIter2, _OIter, _BinaryOperation)
transform(_InputIterator1 __first1, _InputIterator1 __last1,
^
/opt/csw/include/c++/5.2.0/bits/stl_algo.h:4201:5: note: template argument deduction/substitution failed:
ParallelFunctions.cpp:134:27: note: candidate expects 5 arguments, 4 provided
::exp);
^
2.For the r-devel-linux-x86_64-fedora-clang:
hpaML.cpp:754:45: warning: explicitly assigning value of variable of type 'Rcpp::NumericVector' (aka 'Vector<14>') to itself [-Wself-assign-overloaded]
mean_ind, sd_ind = sd_ind,
~~~~~~ ^ ~~~~~~
ParallelFunctions.cpp:46:7: error: no matching function for call to 'transform'
std::transform(input.begin() + begin,
^~~~~~~~~~~~~~
/usr/local/bin/../include/c++/v1/algorithm:1955:1: note: candidate template ignored: couldn't infer template argument '_BinaryOperation'
transform(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2,
^
/usr/local/bin/../include/c++/v1/algorithm:1945:1: note: candidate function template not viable: requires 4 arguments, but 5 were provided
transform(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _UnaryOperation __op)
^
Here is the code for the function where std::tansform and std::exp functions have been called:
// Parallel exp of vectors
struct ParallelVectorExpStruct : public Worker
{
// source matrix
const RVector<double> input;
// destination matrix
RVector<double> output;
// initialize with source and destination
ParallelVectorExpStruct(const NumericVector input, NumericVector output)
: input(input), output(output) {}
// take the exponents of the range of elements requested
void operator()(std::size_t begin, std::size_t end) {
std::transform(input.begin() + begin,
input.begin() + end,
output.begin() + begin,
::exp);
}
};
// Parallel exponent of vector elements
NumericVector ParallelVectorExp(NumericVector x)
{
// allocate the output matrix
NumericVector output(x.size());
// ParallelVectorPowStruct functor
ParallelVectorExpStruct parallelVectorExpStruct(x, output);
// call parallelFor to do the work
parallelFor(0, x.length(), parallelVectorExpStruct);
// return the output matrix
return (output);
}
My descriptions file includes SystemRequirements: GNU make
My makevars file has the following flags
CXX_STD = CXX11
PKG_CXXFLAGS = $(SHLIB_OPENMP_CXXFLAGS)
PKG_LIBS = $(SHLIB_OPENMP_CXXFLAGS) $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS)
PKG_LIBS += $(shell ${R_HOME}/bin/Rscript -e "RcppParallel::RcppParallelLibs()")
Please help me to figure out how to resolve the error. Will be very great full for help!
I have found a strange solution. The idea is to make the following wrapper function:
double exp_parallel(double x)
{
return std::exp(x);
}
Then I substitute exp with exp_parallel yielding:
// Parallel exp of vectors
struct ParallelVectorExpStruct : public Worker
{
// source matrix
const RVector<double> input;
// destination matrix
RVector<double> output;
// initialize with source and destination
ParallelVectorExpStruct(const NumericVector input, NumericVector output)
: input(input), output(output) {}
// take the exponents of the range of elements requested
void operator()(std::size_t begin, std::size_t end) {
std::transform(input.begin() + begin,
input.begin() + end,
output.begin() + begin,
::exp_parallel);
}
};
Maybe the reason is that some systems can't distinguish between std::exp and Rcpp::exp functions.

Error while appling std::bind to function with argument <boost::asio::ip::tcp::socket>?

There's a function accepting an argument with type boost::asio::ip::tcp::socket. But I failed to apply std::bind to it. I've checked template arguments in std::_Bind_helper but no problem found. I've tried both gcc 8.1.0 and clang 6.0.0, and they give the same error.
#include <functional>
#include <boost/asio.hpp>
using namespace std;
namespace asio = boost::asio;
using tcp = asio::ip::tcp;
int c;
void good_f(int) {c=1;}
void good() {
using typeA = int;
auto helper = std::bind(&good_f, typeA(1));
helper();
// OK
}
void fixed_f(tcp::socket &) {c=1;}
void fixed() {
using type1 = tcp::socket;
asio::io_context ioc;
tcp::socket sock(ioc);
auto helper = std::bind(&fixed_f, std::ref(sock));
helper();
// OK
}
void fail_f(tcp::socket &&) {c=1;}
void fail() {
using type1 = tcp::socket;
asio::io_context ioc;
tcp::socket sock(ioc);
// fail_f(std::move(sock));
// OK
auto helper = std::bind(&fail_f, std::move(sock));
helper();
// a.cc:34:5: error: no matching function for call to object of type 'std::_Bind<void (*(boost::asio::basic_stream_socket<boost::asio::ip::tcp>))(boost::asio::basic_stream_socket<boost::asio::ip::tcp> &&)>'
// helper();
// ^~~~~~
}
Compilation log and errors:
recolic#RECOLICPC ~/tmp> clang++ --version
clang version 6.0.0 (tags/RELEASE_600/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
recolic#RECOLICPC ~/tmp> clang++ -c a.cc
a.cc:39:5: error: no matching function for call to object of type 'std::_Bind<void (*(boost::asio::basic_stream_socket<boost::asio::ip::tcp>))(boost::asio::basic_stream_socket<boost::asio::ip::tcp> &&)>'
helper();
^~~~~~
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/8.1.0/../../../../include/c++/8.1.0/functional:480:2: note: candidate template ignored: substitution failure [with _Args = <>]: no type named 'type' in 'std::result_of<void
(*&(boost::asio::basic_stream_socket<boost::asio::ip::tcp> &))(boost::asio::basic_stream_socket<boost::asio::ip::tcp> &&)>'
operator()(_Args&&... __args)
^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/8.1.0/../../../../include/c++/8.1.0/functional:491:2: note: candidate template ignored: substitution failure [with _Args = <>]: no type named 'type' in 'std::result_of<void (*const &(const
boost::asio::basic_stream_socket<boost::asio::ip::tcp> &))(boost::asio::basic_stream_socket<boost::asio::ip::tcp> &&)>'
operator()(_Args&&... __args) const
^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/8.1.0/../../../../include/c++/8.1.0/functional:509:2: note: candidate template ignored: substitution failure [with _Args = <>]: no type named 'type' in 'std::result_of<void (*volatile &(volatile
boost::asio::basic_stream_socket<boost::asio::ip::tcp> &))(boost::asio::basic_stream_socket<boost::asio::ip::tcp> &&)>'
operator()(_Args&&... __args) volatile
^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/8.1.0/../../../../include/c++/8.1.0/functional:521:2: note: candidate template ignored: substitution failure [with _Args = <>]: no type named 'type' in 'std::result_of<void (*const volatile &(const volatile
boost::asio::basic_stream_socket<boost::asio::ip::tcp> &))(boost::asio::basic_stream_socket<boost::asio::ip::tcp> &&)>'
operator()(_Args&&... __args) const volatile
^
1 error generated.
I'm not sure what caused this error. Could you please give me any suggestions?
void fail_f_1(tcp::socket);
std::bind(&fail_f_1, tcp::socket(io_context));
This solution fails because boost::asio::ip::tcp::socket is noncopyable.
void fail_f_2(tcp::socket &&);
std::bind(&fail_f_2, std::move(tcp::socket(io_context)));
This solution fails because std::bind pass bound arguments as lvalues, rather than rvalue. fixed_f is a good solution.
If you have to pass rvalue-reference as bound argument, this answer will help.

GCC cannot deduce auto return type from a template function?

I've a simple template function do_something which returns an integer: 123.
template<typename T>
auto do_something(T input) {
std::this_thread::sleep_for(std::chrono::seconds(1));
return 123;
}
int main(int argc, char *argv[]) {
std::function<int(void)> function = std::bind(do_something<int>, 12);
function();
return 0;
}
With GCC 6.1.1, I get this error:
test.cpp: In function ‘int main(int, char**)’:
test.cpp:16:70: error: no matching function for call to ‘bind(<unresolved overloaded function type>, int)’
std::function<int(void)> function = std::bind(do_something<int>, 12);
^
In file included from /usr/include/c++/6.1.1/thread:39:0,
from test.cpp:4:
/usr/include/c++/6.1.1/functional:1331:5: note: candidate: template<class _Func, class ... _BoundArgs> typename std::_Bind_helper<std::__is_socketlike<_Func>::value, _Func, _BoundArgs ...>::type std::bind(_Func&&, _BoundArgs&& ...)
bind(_Func&& __f, _BoundArgs&&... __args)
^~~~
/usr/include/c++/6.1.1/functional:1331:5: note: template argument deduction/substitution failed:
test.cpp:16:70: note: couldn't deduce template parameter ‘_Func’
std::function<int(void)> function = std::bind(do_something<int>, 12);
^
In file included from /usr/include/c++/6.1.1/thread:39:0,
from test.cpp:4:
/usr/include/c++/6.1.1/functional:1359:5: note: candidate: template<class _Result, class _Func, class ... _BoundArgs> typename std::_Bindres_helper<_Result, _Func, _BoundArgs>::type std::bind(_Func&&, _BoundArgs&& ...)
bind(_Func&& __f, _BoundArgs&&... __args)
^~~~
/usr/include/c++/6.1.1/functional:1359:5: note: template argument deduction/substitution failed:
test.cpp:16:70: note: couldn't deduce template parameter ‘_Result’
std::function<int(void)> function = std::bind(do_something<int>, 12);
As you can see, the compiler cannot deduce the result type of the function.
Note that: clang++ 3.8.0 can compile that without any errors.
So my question: is there a way to specify the expected return value from a template function like in this case?
It looks like the compiler isn't sure about the type of the do_something<int> - and I'm not sure if this is a compiler issue, or a language issue - but you can force the compiler to get its types sorted out by using do_something<int> in a relatively trivial way before hand. For example the following compiles OK with both gcc and clang trunk versions (according to godbolt).
#include <functional>
template<typename T>
auto do_something(T input) {
return 123;
}
// Make the compiler workout the type of do_something<int> so we can use it later.
auto f = do_something<int>;
int main(int argc, char *argv[]) {
std::function<int(void)> function = std::bind(do_something<int>, 12);
function();
return 0;
}

using std::async with template functions

How can I, or, can I, pass a template function to async?
Here is the code:
//main.cpp
#include <future>
#include <vector>
#include <iostream>
#include <numeric>
int
main
()
{
std::vector<double> v(16,1);
auto r0 = std::async(std::launch::async,std::accumulate,v.begin(),v.end(),double(0.0));
std::cout << r0.get() << std::endl;
return 0;
}
Here are the error messages:
^
a.cpp:13:88: note: candidates are:
In file included from a.cpp:1:0:
/usr/include/c++/4.8/future:1523:5: note: template std::future::type> std::async(std::launch, _Fn&&, _Args&& ...)
async(launch __policy, _Fn&& __fn, _Args&&... __args)
^
/usr/include/c++/4.8/future:1523:5: note: template argument deduction/substitution failed:
a.cpp:13:88: note: couldn't deduce template parameter ‘_Fn’
auto r0 = std::async(std::launch::async,std::accumulate,v.begin(),v.end(),double(0.0));
^
In file included from a.cpp:1:0:
/usr/include/c++/4.8/future:1543:5: note: template std::future::type> std::async(_Fn&&, _Args&& ...)
async(_Fn&& __fn, _Args&&... __args)
^
/usr/include/c++/4.8/future:1543:5: note: template argument deduction/substitution failed:
/usr/include/c++/4.8/future: In substitution of ‘template std::future::type> std::async(_Fn&&, _Args&& ...) [with _Fn = std::launch; _Args = {}]’:
a.cpp:13:88: required from here
/usr/include/c++/4.8/future:1543:5: error: no type named ‘type’ in ‘class std::result_of’
The problem is that to pass the second argument to std::async the compiler has to turn the expression &std::accumulate into a function pointer, but it doesn't know which specialization of the function template you want. To a human it's obvious you want the one that can be called with the remaining arguments to async, but the compiler doesn't know that and has to evaluate each argument separately.
As PiotrS.'s answer says, you can tell the compiler which std::accumulate you want with an explicit template argument list or by using a cast, or alternatively you can just use a lambda expression instead:
std::async(std::launch::async,[&] { return std::accumulate(v.begin(), v.end(), 0.0); });
Inside the body of the lambda the compiler performs overload resolution for the call to std::accumulate and so it works out which std::accumulate to use.
You have to disambiguate between possible instantiations by either explicitly passing the template arguments or using static_cast, so:
auto r0 = std::async(std::launch::async
, &std::accumulate<decltype(v.begin()), double>
, v.begin()
, v.end()
, 0.0);
or:
auto r0 = std::async(std::launch::async
, static_cast<double(*)(decltype(v.begin()), decltype(v.end()), double)>(&std::accumulate)
, v.begin()
, v.end()
, 0.0);

Loki's Functor with variadic templates

I have a question about the Functor implementation of the library Loki.
I am doing some changes in order to make it work with variadic templates instead of having lines and lines of template specialization. The problem is that I am trying to use typedef for variadic template and I do not understand my error, that is why I could use some help from experts...
Here is the header file.
I tested it with a simple example:
static void foo()
{
std::cout << "foo !!!" << std::endl;
}
int
main( int argc, const char** argv )
{
Functor<void, void> static_func(foo);
static_func();
}
Which gives me this error
/home/test/src/EntryPoint.cpp:237:17: error: no match for call to ‘(Functor<void, void>) ()’
In file included from /home/test/src/EntryPoint.cpp:231:0:
/home/test/include/FunctorTest.h:217:7: note: candidate is:
/home/test/include/FunctorTest.h:292:16: note: Functor<R, TList>::ResultType Functor<R, TList>::operator()(Functor<R, TList>::MyList&&) const [with R = void; TList = {void}; Functor<R, TList>::ResultType = void; Functor<R, TList>::MyList = variadic_typedef<void>]
/home/test/include/FunctorTest.h:292:16: note: candidate expects 1 argument, 0 provided
/home/test/src/EntryPoint.cpp: At global scope:
/home/test/src/EntryPoint.cpp:234:1: warning: unused parameter ‘argc’ [-Wunused-parameter]
/home/test/src/EntryPoint.cpp:234:1: warning: unused parameter ‘argv’ [-Wunused-parameter]
In file included from /home/test/src/EntryPoint.cpp:231:0:
/home/test/include/FunctorTest.h: In instantiation of ‘FunctorHandler<ParentFunctor, Fun>::ResultType FunctorHandler<ParentFunctor, Fun>::operator()(FunctorHandler<ParentFunctor, Fun>::MyList&&) [with ParentFunctor = Functor<void, void>; Fun = void (*)(); FunctorHandler<ParentFunctor, Fun>::ResultType = void; FunctorHandler<ParentFunctor, Fun>::MyList = variadic_typedef<void>]’:
/home/test/src/EntryPoint.cpp:247:1: required from here
/home/test/include/FunctorTest.h:159:49: error: no matching function for call to ‘forward(FunctorHandler<Functor<void, void>, void (*)()>::MyList&)’
/home/test/include/FunctorTest.h:159:49: note: candidates are:
In file included from /usr/include/c++/4.7/bits/stl_pair.h:61:0,
from /usr/include/c++/4.7/utility:72,
from /home/jean/Lib/vitals/include/CLPair.h:28,
from /home/jean/Lib/vitals/include/CLMap.h:27,
from /home/jean/Lib/vitals/include/HTCmdLineParser.h:27,
from /home/test/include/EntryPoint.h:23,
from /home/test/src/EntryPoint.cpp:22:
/usr/include/c++/4.7/bits/move.h:77:5: note: template<class _Tp> constexpr _Tp&& std::forward(typename std::remove_reference<_From>::type&)
/usr/include/c++/4.7/bits/move.h:77:5: note: template argument deduction/substitution failed:
In file included from /home/test/src/EntryPoint.cpp:231:0:
/home/test/include/FunctorTest.h:159:49: note: cannot convert ‘parms’ (type ‘FunctorHandler<Functor<void, void>, void (*)()>::MyList {aka variadic_typedef<void>}’) to type ‘std::remove_reference<convert_in_tuple<variadic_typedef<void> > >::type& {aka convert_in_tuple<variadic_typedef<void> >&}’