Compilation error while passing two variadic parameter in c++11 - c++

I need to queue task as function pointers. The argument for function pointer is a list of parameters and a callback.
I created a class which stores theses tasks. Now I need to write a template method which takes a function pointer, parameters and callback.
I tried creating below class, but is not compiling...
#include <iostream>
#include <vector>
#include <functional>
#include <memory>
class TaskScheduler {
public:
TaskScheduler() = default;
virtual ~TaskScheduler() {}
template <typename... TParam>
struct Callback {
using Type = std::function<void(TParam...)>;
};
template<typename TCallback, typename... TRequestParam>
void queue(void (*requestFunction)(TRequestParam..., typename TCallback::Type),
TRequestParam... args, typename TCallback::Type callback) {
doQueue([this, requestFunction, args..., callback](){
requestFunction(args..., callback);
});
}
void fire() {
for (auto task: mTasks) {
task();
}
}
protected:
void doQueue(std::function<void()> task) {
mTasks.push_back(task);
}
std::vector<std::function<void()>> mTasks;
};
class Test1 {};
class Test2 {};
class Test3 {};
void function1(Test1 *a1, std::shared_ptr<Test2> a2, std::function<void(std::shared_ptr<Test2>)> a3) {
}
int main(int, char **) {
TaskScheduler ns;
Test1 *test1Ptr = 0;
auto test2Sptr = std::make_shared<Test2>();
std::function<void(std::shared_ptr<Test2>)> callback = [](std::shared_ptr<Test2>){};
ns.queue<TaskScheduler::Callback<std::shared_ptr<Test2>>, Test1 *, std::shared_ptr<Test2>>(&function1, test1Ptr, test2Sptr, callback);
ns.fire();
}
With clang I get the error,
mtest.cc:55:8: error: no matching member function for call to 'queue'
ns.queue<TaskScheduler::Callback<std::shared_ptr<Test2>>, Test1 *, std::shared_ptr<Test2>>(&function1, test1Ptr, test2Sptr, callback);
~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mtest.cc:17:10: note: candidate template ignored: failed template argument deduction
void queue(void (*requestFunction)(TRequestParam..., typename TCallback::Type),

Related

How to create a simple version of std::function class

Suppose that I want to create a simple version ofstd::function, which has following behaviors:
1. function(){} -> A void constructor
2. function(_ReturnType, Args... vlist) -> To convert function pointer to a funcion object
3. _ReturnType operator() (_ArgTypes... vlist) -> To call function by fn(Args...)
I have already tried to write down a version, but it seems to fail during compiling...
I design it like this:
template <typename ReType, typename... _ArgTypes>
class function
{
protected:
ReType(*fn) = NULL;
public:
function() {}
function(ReType R, _ArgTypes... vlist) { fn = R; }
ReType operator()(_ArgTypes... vlist)
{
return fn(vlist...);
}
};
With compiler error:
In file included from main.cpp:11:
functional.h: In instantiation of 'class nuts::function<double(double)>':
main.cpp:102:27: required from here
functional.h:16:16: error: function returning a function
ReType operator()(_ArgTypes... vlist)
^~~~~~~~
main.cpp: In function 'int main()':
main.cpp:103:19: error: no match for call to '(nuts::function<double(double)>) (double)'
std::cout << fn(2.0) << std::endl;
^
Based on the solution given by #mch
template <typename FuncType>
class function
{
FuncType *(fn) = NULL;
public:
function(FuncType R) : fn{R} {}
template <typename... _ArgTypes>
auto operator()(_ArgTypes... vlist)
{
return fn(vlist...);
}
};

Passing function into function with std::function and template argument

I am trying to pass a pointer to the predicate function into the Foo and Bar functions.
The Bar function works correctly, but the Foo function raises a compile-time error:
error: no matching function for call to Foo<int>(bool (&)(int))
Why does the compiler raise an error?
Is there any difference between Foo's and Bar's template arguments types after Args' unpacking?
#include <functional>
bool predicate(int a) {
return (a > 5);
}
// sizeof...(Args) == 1 and I suppose it is int
template<typename... Args>
void Foo(std::function<bool(Args...)> predicate) {
// clang: note: candidate template ignored:
// could not match 'function<bool (int, type-parameter-0-0...)>'
// against 'bool (*)(int)'
}
template<typename Args>
void Bar(std::function<bool(Args)> predicate) {
}
int main(int argc, char const *argv[]) {
// gcc: error: no matching function for call to
// 'Foo<int>(bool (&)(int))'
Foo<int>(predicate);
Bar<int>(predicate);
return 0;
}
See Compiler Explorer for a live example.
I also tried to change the Foo function a little and it works somehow:
template<typename... Args>
void Foo(bool(*predicate)(Args...)) {
std::function<bool(Args...)> func(predicate);
}
I want to have std::function type argument in the Foo function, but I don't know how to do it
The error is because the exact type of std::function is not same as predicate. To get around this, you can explicitly call the constructor of std::function:
int main() {
Foo<int>( std::function<bool(int){predicate} );
//OR
Foo<int>( {predicate} );
return 0;
}

Pass a templatized type to a member function in C++

I'm trying to write a member function that can instantiate an object of a custom type (templatized), initializing its const& member to a local object of the function.
This is consistent since the lifetime of the custom type object is the same as the local_object.
The objective is caching some metadata of the local object because they don't change during its lifetime. The operator() (or any member function) computes some values, then used later in func, and the objective is offering a hook to change the behaviour of func.
Please no polymorphic solutions (currently used) due to (profiled) slowness.
This is a M(N)WE:
#include <vector>
class cls {
public:
template <typename Custom> int func() {
std::vector<int> local_object{0, 14, 32};
Custom c(local_object, 42);
return c();
}
};
template<typename AType> class One {
public:
One(const AType& obj, const int n): objref(obj), param(n), member_that_should_depend_on_objref(obj.size()) {}
int operator()() { return 42; }
private:
const AType& objref;
const int param;
float member_that_should_depend_on_objref;
};
template<typename AType> class Two {
public:
Two(const AType& obj, const int n): objref(obj), param(n), other_member_that_should_depend_on_objref(obj.empty()), other_dependent_member(obj.back()) {}
int operator()() { return 24; }
private:
const AType& objref;
const int param;
bool other_member_that_should_depend_on_objref;
int other_dependent_member;
};
int main() {
cls myobj;
auto a = myobj.func<One>();
auto b = (myobj.func<Two>)();
}
G++ 5.3.0 says
tmp.cpp: In function 'int main()':
tmp.cpp:34:30: error: no matching function for call to 'cls::func()'
auto a = myobj.func<One>();
^
tmp.cpp:4:36: note: candidate: template<class Custom> int cls::func()
template <typename Custom> int func() {
^
tmp.cpp:4:36: note: template argument deduction/substitution failed:
tmp.cpp:35:32: error: no matching function for call to 'cls::func()'
auto b = (myobj.func<Two>)();
^
tmp.cpp:4:36: note: candidate: template<class Custom> int cls::func()
template <typename Custom> int func() {
^
tmp.cpp:4:36: note: template argument deduction/substitution failed:
Clang++ 3.7.1 says:
tmp.cpp:34:20: error: no matching member function for call to 'func'
auto a = myobj.func<One>();
~~~~~~^~~~~~~~~
tmp.cpp:4:36: note: candidate template ignored: invalid explicitly-specified argument for template
parameter 'Custom'
template <typename Custom> int func() {
^
tmp.cpp:35:21: error: no matching member function for call to 'func'
auto b = (myobj.func<Two>)();
~~~~~~~^~~~~~~~~~
tmp.cpp:4:36: note: candidate template ignored: invalid explicitly-specified argument for template
parameter 'Custom'
template <typename Custom> int func() {
^
2 errors generated.
auto a = myobj.func<One>();
is wrong since One is a class template, not a class. Use
auto a = myobj.func<One<SomeType>>();
It's not clear from your code what SomeType should be.
Update
If you want to use:
auto a = myobj.func<One>();
you need to change func to use a template template parameter:
class cls {
public:
template <template <class> class Custom > int func() {
std::vector<int> local_object{0, 14, 32};
Custom<std::vector<int>> c(local_object, 42);
return c();
}
};
Perhaps that was your intention.

template argument deduction/substitution failed, when using std::function and std::bind

I have a compile error when using std::function in a templated member function, the following code is a simple example:
#include <functional>
#include <memory>
using std::function;
using std::bind;
using std::shared_ptr;
class Test {
public:
template <typename T>
void setCallback(function<void (T, int)> cb);
};
template <typename T>
void Test::setCallback(function<void (T, int)> cb)
{
// do nothing
}
class TestA {
public:
void testa(int a, int b) { }
};
int main()
{
TestA testA;
Test test;
test.setCallback(bind(&TestA::testa, &testA, std::placeholders::_1, std::placeholders::_2));
return 0;
}
And come with the following compile error:
testtemplate.cpp: In function ‘int main()’:
testtemplate.cpp:29:92: error: no matching function for call to
‘Test::setCallback(std::_Bind_helper)(int, int),
TestA, const std::_Placeholder<1>&, const
std::_Placeholder<2>&>::type)’
testtemplate.cpp:29:92: note: candidate is: testtemplate.cpp:10:7:
note: template void Test::setCallback(std::function)
testtemplate.cpp:10:7: note: template argument
deduction/substitution failed:
testtemplate.cpp:29:92: note: ‘std::_Bind(TestA*, std::_Placeholder<1>,
std::_Placeholder<2>)>’ is not derived from ‘std::function’
I'm using C++11 and g++ 4.7
To figure out the problem let separate statements:
auto f = bind(&TestA::testa, &testA, _1, _2); // OK
test.setCallback(f); // <<--- Error is here
setCallback needs to know type of T and it can't deduce it from f, so give it a type
test.setCallback<TYPE>(f); // TYPE: int, float, a class, ...
You can make type deduction work with some variant of:
template<typename CALLBACK>
void setCallback(CALLBACK cb) {
typedef CALLBACK::first_argument_type T;
static_assert(is_same_type<CALLBACK,function<void(T,int)>>::value);
...
}
This way CALLBACK can be determined by looking at the argument. It might get into trouble if bind doesn't actually return a std::function but rather something that can be cast as one. I'm not sure.

C++ polymorphism with variadic function parameter

I am sharing with you an issue that I got with a class using variadic function parameters. It is the class Thread shown in the following code. It is a wrapper of std::thread in order to use the function pattern.
I wanted to use polymorphism with this function in inheriting the class Thread into a new class, Functor, but gcc returns the errors bellow:
#include <thread>
#include <iostream>
using namespace std;
template<class... Args>
class Thread
{
public:
virtual void operator()(Args...) = 0;
void run(Args... args)
{
std::thread t(std::forward< Thread<Args...> >(*this), std::forward<Args>(args)...);
t.join();
}
};
template<class... Args>
class Functor : public Thread<Args...>
{
public:
// generates the errors bellow
virtual void operator()(Args... /*args*/)
{
}
// doesnot work since the pure virtual function wants another prototype of function.
// void operator()(int)
// {
// }
};
int main()
{
int a = 12;
Functor<int> f;
f.run(ref(a));
return 0;
}
from t-Thread-args2.cpp:1:
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/tuple: In instantiation of ‘struct std::_Head_base, false>’:
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/tuple:215:12: required from ‘struct std::_Tuple_impl, int>’
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/tuple:507:11: required from ‘class std::tuple, int>’
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/functional:1601:39: required from ‘struct std::_Bind_simple(int)>’
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/thread:133:9: required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = Thread; _Args = {int}]’
t-Thread-args2.cpp:14:83: required from ‘void Thread::run(Args ...) [with Args = {int}]’
t-Thread-args2.cpp:42:17: required from here
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/tuple:166:13: error: cannot declare field ‘std::_Head_base, false>::_M_head_impl’ to be of abstract type ‘Thread’
t-Thread-args2.cpp:7:7: note: because the following virtual functions are pure within ‘Thread’:
t-Thread-args2.cpp:10:18: note: void Thread::operator()(Args ...) [with Args = {int}]
I dont really understand the error since the pure virtual function was well defined in the deriveted class. However, in moving the function run() into the derivated class (Functor) it works.
Thanks in advance,
Caner
As per [thread.thread.constr]§3, the type of the first argument of the std::thread constructor is F&&, with the requirement that F is MoveConstructible. In your case, F is Thread, which is not MoveConstructible.
In other words, the std::thread needs to store the functor by value, and you're forwarding the functor as Thread, which is abstract.
The problem is:
std::forward< Thread<Args...> >(*this)
which tries to copy the Thread sub-object. Luckily it's abstract, so you get a compile error rather than unexpected runtime behaviour.
You want a reference wrapper instead:
std::ref(*this)
I considered the multiple advice provided by the participants to this topic including the use of std::ref and would like to share with you the working code version solving the issues I got with the previous code.
#include <thread>
#include <iostream>
using namespace std;
template<class... Args>
class Thread
{
public:
virtual void operator()(Args...) = 0;
void run(Args... args)
{
std::thread t(std::ref(*this), args...);
t.join();
}
};
template<class... Args>
class Functor : public Thread<Args...>
{
public:
void operator()(int)
{
while (1)
{
cout << "42 "; cout.flush();
}
}
};
int main()
{
int a = 12;
Functor<int> f;
f.run(ref(a));
return 0;
}
Thanks again.