Related
i search on google how to store and to execute functions (template function or not) passing in queue but i didn't find an enough good answer...
this is my code
Window.h
struct QueueEventFunction {
std::vector<std::function<void()>> v; // stores the functions and arguments
// as zero argument lambdas
template <typename F,/*template <typename U, typename = std::allocator<U> >*/ typename ...Args>
void Enqueue(F (*f), Args... args)
{
v.push_back([=] { f(args...); }); // add function and arguments
// as zero argument lambdas
// that capture the function and arguments
}
void CallAll()
{
for (auto f : v)
f(); // calls all the functions
}
};
class Window : public sf::RenderWindow {
public:
Window(sf::VideoMode window, const std::string& title, sf::Uint32 style = 7U, sf::ContextSettings settings = sf::ContextSettings());
~Window();
template <typename F, /*template <typename ...U > */typename ...Args>
void addQueue(F (*f), Args...args);
void execQueue();
private:
QueueEventFunction queue;
}
template <typename F, /*template <typename ...U >*/ typename ...Args>
void Window::addQueue(F (*f), Args...args) {
queue.Enqueue(f, std::forward<Args>(args)...);
}
void Window::execQueue() {
queue.CallAll();
}
TestWindow.cpp
template<typename T>
void add(T a, T b) {
return a + b;
}
class foo{
public:
template<typename T> T add( T a, T b){ return a+ b;}
};
int main() {
Window window(sf::VideoMode(600, 600), "Test Window",7U,sf::ContextSettings());
window.addQueue(add<int>,1,2); // doesn't work
foo bar;
window.addQueue(&foo::add<int>,1,2); // doesn"t work
window.addQueue(bar.add<int>(1,2)); // doesn"t work
return 0;
}
i got a external symbol error.
and if i put a function member class it simply doesn't work. (compilation error)
have you got an idea to correctly make the function addQueue<> with args ?
The big problem with your code is that you take the function pointer as a pointer
template <typename F, typename ...Args>
void Enqueue(F (*f), Args... args)
and
template <typename F, typename ...Args>
void addQueue(F (*f), Args...args);
What you really want is
template <typename F, typename ...Args>
void Enqueue(F f, Args... args)
and
template <typename F, typename ...Args>
void addQueue(F f, Args...args);
And then you can pass any callable thing. Then you can use it with results of bind, lambdas, class member functions, class static member functions, and normal functions.
Then you can use it like
template<typename T>
int add(T a, T b) {
std::cout << "add(" << a << "," << b << ") -> " << a+b << "\n";
return a + b;
}
class foo{
public:
template<typename T>
T add( T a, T b) {
std::cout << "foo::add(" << a << "," << b << ") -> " << a+b << "\n";
return a + b;
}
template<typename T>
static T static_add( T a, T b) {
std::cout << "foo::static_add(" << a << "," << b << ") -> " << a+b << "\n";
return a + b;
}
};
int main() {
Window window(sf::VideoMode(600, 600),"Test Window",7U,sf::ContextSettings());
foo bar;
auto bar_add = [&bar](auto a,auto b){ return bar.add<int>(a,b); };
auto bind_add = std::bind(&foo::add<int>, &bar, std::placeholders::_1, std::placeholders::_2);
window.addQueue(bind_add,5,2);
window.addQueue(bar_add,5,2);
window.addQueue(add<int>,5,2);
window.addQueue(foo::static_add<int>,5,2);
window.execQueue();
return 0;
}
Try it here https://www.onlinegdb.com/t9WczrL-c
#include <iostream>
class A
{
public:
A(bool b, int i)
: b_(b) , i_(i) {}
void print()
{
std::cout << b_ << " " << i_ << "\n";
}
private:
bool b_;
int i_;
};
class B
{
public:
B(double d)
: d_(d) {}
void print()
{
std::cout << d_ << "\n";
}
private:
double d_;
};
template<class T=A, typename ... Args>
void f(int a, Args ... args)
{
std::cout << a << std::endl;
T t(args...);
t.print();
}
int main()
{
f(1,false,3);
f<A>(2,true,1);
f<B>(3,2.0);
}
The code above compiles and runs fine. But:
// (class A and B declared as above)
template<class T, typename ... Args>
class F
{
public:
F(int a, Args ... args)
{
std::cout << a << std::endl;
T t(args...);
t.print();
}
};
int main()
{
F<A>(4,true,1);
F<B>(5,2.0);
}
fails to compile with message :
main.cpp: In function ‘int main()’: main.cpp:64:18: error: no matching
function for call to ‘F::F(int, bool, int)’
F(4,true,1);
With your current code, your instantiation of F<A> makes the Args template argument empty, which means the constructor only have the a argument, not args.
It seems that you want only the constructor to have a template parameter pack, not the whole class:
template<class T>
class F
{
public:
template<typename ... Args>
F(int a, Args ... args)
{
std::cout << a << std::endl;
T t(args...);
t.print();
}
};
You made the class a template, not the constructor.
But only the constructor "knows" what the template arguments should be, because those are deduced from the constructor arguments.
That doesn't work.
Instead, you can make the constructor a template, not the class.
Depending of your needs, it should be:
template<class T, typename ... Args>
class F
{
public:
F(int a, Args ... args)
{
std::cout << a << std::endl;
T t(args...);
t.print();
}
};
int main()
{
F<A, bool, int>(4,true,1);
F<B, double>(5,2.0);
}
or
template<class T>
class F
{
public:
template <typename ... Args>
F(int a, Args ... args)
{
std::cout << a << std::endl;
T t(args...);
t.print();
}
};
int main()
{
F<A>(4,true,1);
F<B>(5,2.0);
}
I'm trying to create a generic wrapper function that takes a function as a template argument and takes the same arguments as that function as its arguments. For example:
template <typename F, F func>
/* return type of F */ wrapper(Ts... Args /* not sure how to get Ts*/)
{
// do stuff
auto ret = F(std::forward<Ts>(args)...);
// do some other stuff
return ret;
}
The solution needs to be castable to a function pointer with the same type as func so that I can pass it to a C api. In other words, the solution needs to be a function and not a function object. Most importantly, I need to be able to do work in the wrapper function.
If the inline comments aren't clear, I'd like to be able to do something like the following:
struct c_api_interface {
int (*func_a)(int, int);
int (*func_b)(char, char, char);
};
int foo(int a, int b)
{
return a + b;
}
int bar(char a, char b, char c)
{
return a + b * c;
}
c_api_interface my_interface;
my_interface.func_a = wrapper<foo>;
my_interface.func_b = wrapper<bar>;
I looked for related posts and found these, but none of them are quite what I'm trying to do. Most of these posts concern function objects. Is what I'm trying to do even possible?
Function passed as template argument
Function wrapper via (function object) class (variadic) template
How does wrapping a function pointer and function object work in generic code?
How do I get the argument types of a function pointer in a variadic template class?
Generic functor for functions with any argument list
C++ Functors - and their uses
In response to the first 2 responses, I edited the question to make it clear that I need to be able to do work in the wrapper function (i.e. modify some global state before and after the call to the wrapped function)
template<class F, F f> struct wrapper_impl;
template<class R, class... Args, R(*f)(Args...)>
struct wrapper_impl<R(*)(Args...), f> {
static R wrap(Args... args) {
// stuff
return f(args...);
}
};
template<class F, F f>
constexpr auto wrapper = wrapper_impl<F, f>::wrap;
Use as wrapper<decltype(&foo), foo>.
#include <utility>
#include <iostream>
struct c_api_interface { int (*func_a)(int, int); int (*func_b)(char, char, char); };
int foo(int a, int b) { return a + b; }
int bar(char a, char b, char c) { return a + b * c; }
template<typename Fn, Fn fn, typename... Args>
typename std::result_of<Fn(Args...)>::type
wrapper(Args... args) {
std::cout << "and ....it's a wrap ";
return fn(std::forward<Args>(args)...);
}
#define WRAPIT(FUNC) wrapper<decltype(&FUNC), &FUNC>
int main() {
c_api_interface my_interface;
my_interface.func_a = WRAPIT(foo);
my_interface.func_b = WRAPIT(bar);
std:: cout << my_interface.func_a(1,1) << std::endl;
std:: cout << my_interface.func_b('a','b', 1) << std::endl;
return 0;
}
see http://rextester.com/ZZD18334
you may try something like that (Ugly, but works)
#include <iostream>
#include <functional>
struct wrapper_ctx
{
wrapper_ctx ()
{
std::cout << "Before" << std::endl;
}
~wrapper_ctx ()
{
std::cout << "after" << std::endl;
}
};
template <typename F, typename... Args>
auto executor (F&& f, Args&&... args) -> typename std::result_of<F(Args...)>::type
{
wrapper_ctx ctx;
return std::forward<F>(f)( std::forward<Args>(args)...);
}
template <typename F>
class wrapper_helper;
template<typename Ret, typename... Args>
class wrapper_helper <std::function<Ret(Args...)>>
{
std::function<Ret(Args...)> m_f;
public:
wrapper_helper( std::function<Ret(Args...)> f )
: m_f(f) {}
Ret operator()(Args... args) const
{
return executor (m_f, args...);
}
};
template <typename T>
wrapper_helper<T> wrapper (T f)
{
return wrapper_helper <T>(f);
}
int sum(int x, int y)
{
return x + y;
}
int main (int argc, char* argv [])
{
std::function<int(int, int)> f = sum;
auto w = wrapper (f);
std::cout << "Executing the wrapper" << std::endl;
int z = w(3, 4);
std::cout << "z = " << z << std::endl;
}
you probably need something like
template <typename F>
class Wrapper {
public:
Wrapper(F *func) : function(func) {}
operator F* () { return function; }
F *function;
};
Which you can use like void (*funcPtr)(int) = Wrapper<void(int)>(&someFunction);
I think that will be the concise way to do what you want:
template <typename F>
F* wrapper(F* pFunc)
{
return pFunc;
}
and use it like this:
my_interface.func_a = wrapper(foo);
my_interface.func_a(1, 3);
You may try this
template <class R, class... Args>
struct wrap
{
using funct_type = R(*)(Args...);
funct_type func;
wrap(funct_type f): func(f) {};
R operator()(Args&&... args)
{
//before code block
std::cout << "before calling\n";
R ret=func(std::forward<Args>(args)...);
//after code block
std::cout << "After calling\n";
}
};
use like this for example:
int somefunc(double &f, int x);
auto wrapped_somefunc=wrap{somefunc};
double f=1.0;
int x = 2;
auto result=wrapped_somefunc(f,x);
This one is for c++17 and newer uses auto template parameters:
template <auto func, class... Args>
auto wrap_func(Args... args)
{
std::cout << "before calling wrapped func\n";
auto ret = func(args...);
std::cout << "after calling wrapped func\n";
return ret;
}
use for example:
int some_func(int a, int b);
auto ret = wrap_func<some_func>(2, 3);
#include <cstdio>
#include <string>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/lexical_cast.hpp>
struct CLASS{
template<typename T, typename ... Args>
void enqueue(T const & t, Args const & ... args){
this->concatenate(t,args ...);
}
template<typename T, typename ... Args>
void concatenate(T t, Args ... args){
boost::function<void()> f
= boost::bind(&CLASS::push_,this,
boost::bind(&CLASS::stringer<T const &,
Args const & ...>,
this,boost::ref(t),boost::ref(args)...));
}
template<typename T, typename ... Args>
std::string stringer(T const & t, Args const & ... args){
return stringer(t) + stringer(args...);
}
template <typename T>
std::string stringer(T const & t){
return boost::lexical_cast<std::string>(t);
}
void push_(std::string const & s){
std::fprintf(stderr,"%s\n",s.c_str());
}
};
int main(){
CLASS c;
c.enqueue(42,"hello",35);
// below commented enqueue fails to compile
//c.enqueue("abc", 100," for ", 42000,"sadada ", 4.3, "zzzzz\n",42,42);
return 0;
}
In the main function above, the commented line fails to compile, although the uncommented enqueue does work. I have a feeling the problem is to do with the unwinding of the variadics by the stringer function and boost::bind failing to figure out overloads or something.
How do I solve this problem, so that enqueue works for any combination of inputs?
under c++11,we cannot bind a overload function.
but there is solution under C++14:
example:
struct ulong_ip_tag{};
struct string_ip_tag{};
struct resolved_ip_tag{};
struct invalid_ip_tag{};
template<typename _Type, typename _Handler>
void handler(_Handler, _Type)
{
std::cout << "other type" << std::endl;
}
template<typename _Handler>
void handler(_Handler, resolved_ip_tag)
{
std::cout << typeid(resolved_ip_tag).name() << std::endl;
}
template<typename _Handler>
void handler(_Handler, string_ip_tag)
{
std::cout << typeid(string_ip_tag).name() << std::endl;
}
template<typename _Handler>
void handler(_Handler, ulong_ip_tag)
{
std::cout << typeid(ulong_ip_tag).name() << std::endl;
}
void test(){}
int main()
{
//auto--- under c++14
auto b = [](auto arg1,auto arg2){handler(arg1,arg2)};
std::bind(b,test,ulong_ip_tag());
}
I want to write a C++ metafunction is_callable<F, Arg> that defines value to be true, if and only if the type F has the function call operator of the form SomeReturnType operator()(const Arg &). For example, in the following case
struct foo {
void operator(const int &) {}
};
I want is_callable<foo, int &> to be false and is_callable<foo, const int &> to be true. This is what I have so far :
#include <memory>
#include <iostream>
template<typename F, typename Arg>
struct is_callable {
private:
template<typename>
static char (&test(...))[2];
template<unsigned>
struct helper {
typedef void *type;
};
template<typename UVisitor>
static char test(
typename helper<
sizeof(std::declval<UVisitor>()(std::declval<Arg>()), 0)
>::type
);
public:
static const bool value = (sizeof(test<F>(0)) == sizeof(char));
};
struct foo {
void operator()(const int &) {}
};
using namespace std;
int main(void)
{
cout << is_callable<foo, int &>::value << "\n";
cout << is_callable<foo, const int &>::value << "\n";
return 0;
}
This prints 1 and 1, but I want 0 and 1 because foo only defines void operator()(const int &).
After hours of playing around and some serious discussions in the C++ chat room, we finally got a version that works for functors with possibly overloaded or inherited operator() and for function pointers, based on #KerrekSB's and #BenVoigt's versions.
#include <utility>
#include <type_traits>
template <typename F, typename... Args>
class Callable{
static int tester[1];
typedef char yes;
typedef yes (&no)[2];
template <typename G, typename... Brgs, typename C>
static typename std::enable_if<!std::is_same<G,C>::value, char>::type
sfinae(decltype(std::declval<G>()(std::declval<Brgs>()...)) (C::*pfn)(Brgs...));
template <typename G, typename... Brgs, typename C>
static typename std::enable_if<!std::is_same<G,C>::value, char>::type
sfinae(decltype(std::declval<G>()(std::declval<Brgs>()...)) (C::*pfn)(Brgs...) const);
template <typename G, typename... Brgs>
static char sfinae(decltype(std::declval<G>()(std::declval<Brgs>()...)) (G::*pfn)(Brgs...));
template <typename G, typename... Brgs>
static char sfinae(decltype(std::declval<G>()(std::declval<Brgs>()...)) (G::*pfn)(Brgs...) const);
template <typename G, typename... Brgs>
static yes test(int (&a)[sizeof(sfinae<G,Brgs...>(&G::operator()))]);
template <typename G, typename... Brgs>
static no test(...);
public:
static bool const value = sizeof(test<F, Args...>(tester)) == sizeof(yes);
};
template<class R, class... Args>
struct Helper{ R operator()(Args...); };
template<typename R, typename... FArgs, typename... Args>
class Callable<R(*)(FArgs...), Args...>
: public Callable<Helper<R, FArgs...>, Args...>{};
Live example on Ideone. Note that the two failing tests are overloaded operator() tests. This is a GCC bug with variadic templates, already fixed in GCC 4.7. Clang 3.1 also reports all tests as passed.
If you want operator() with default arguments to fail, there is a possible way to do that, however some other tests will start failing at that point and I found it as too much hassle to try and correct that.
Edit: As #Johannes correctly notes in the comment, we got a little inconsistency in here, namely that functors which define a conversion to function pointer will not be detected as "callable". This is, imho, pretty non-trivial to fix, as such I won't bother with it (for now). If you absolutely need this trait, well, leave a comment and I'll see what I can do.
Now that all this has been said, IMHO, the idea for this trait is stupid. Why whould you have such exact requirements? Why would the standard is_callable not suffice?
(Yes, I think the idea is stupid. Yes, I still went and built this. Yes, it was fun, very much so. No, I'm not insane. Atleast that's what I believe...)
(with apologies to Kerrek for using his answer as a starting point)
EDIT: Updated to handle types without any operator() at all.
#include <utility>
template <typename F, typename Arg>
struct Callable
{
private:
static int tester[1];
typedef char yes;
typedef struct { char array[2]; } no;
template <typename G, typename Brg>
static char sfinae(decltype(std::declval<G>()(std::declval<Brg>())) (G::*pfn)(Brg)) { return 0; }
template <typename G, typename Brg>
static char sfinae(decltype(std::declval<G>()(std::declval<Brg>())) (G::*pfn)(Brg) const) { return 0; }
template <typename G, typename Brg>
static yes test(int (&a)[sizeof(sfinae<G,Brg>(&G::operator()))]);
template <typename G, typename Brg>
static no test(...);
public:
static bool const value = sizeof(test<F, Arg>(tester)) == sizeof(yes);
};
struct Foo
{
int operator()(int &) { return 1; }
};
struct Bar
{
int operator()(int const &) { return 2; }
};
struct Wazz
{
int operator()(int const &) const { return 3; }
};
struct Frob
{
int operator()(int &) { return 4; }
int operator()(int const &) const { return 5; }
};
struct Blip
{
template<typename T>
int operator()(T) { return 6; }
};
struct Boom
{
};
struct Zap
{
int operator()(int) { return 42; }
};
#include <iostream>
int main()
{
std::cout << "Foo(const int &): " << Callable<Foo, int const &>::value << std::endl
<< "Foo(int &): " << Callable<Foo, int &>::value << std::endl
<< "Bar(const int &): " << Callable<Bar, const int &>::value << std::endl
<< "Bar(int &): " << Callable<Bar, int &>::value << std::endl
<< "Zap(const int &): " << Callable<Zap , const int &>::value << std::endl
<< "Zap(int&): " << Callable<Zap , int &>::value << std::endl
<< "Wazz(const int &): " << Callable<Wazz, const int &>::value << std::endl
<< "Wazz(int &): " << Callable<Wazz, int &>::value << std::endl
<< "Frob(const int &): " << Callable<Frob, const int &>::value << std::endl
<< "Frob(int &): " << Callable<Frob, int &>::value << std::endl
<< "Blip(const int &): " << Callable<Blip, const int &>::value << std::endl
<< "Blip(int &): " << Callable<Blip, int &>::value << std::endl
<< "Boom(const int &): " << Callable<Boom, const int &>::value << std::endl
<< "Boom(int&): " << Callable<Boom, int &>::value << std::endl;
}
Demo: http://ideone.com/T3Iry
Here's something I hacked up which may or may not be what you need; it does seem to give true (false) for (const) int &...
#include <utility>
template <typename F, typename Arg>
struct Callable
{
private:
typedef char yes;
typedef struct { char array[2]; } no;
template <typename G, typename Brg>
static yes test(decltype(std::declval<G>()(std::declval<Brg>())) *);
template <typename G, typename Brg>
static no test(...);
public:
static bool const value = sizeof(test<F, Arg>(nullptr)) == sizeof(yes);
};
struct Foo
{
int operator()(int &) { return 1; }
// int operator()(int const &) const { return 2; } // enable and compare
};
#include <iostream>
int main()
{
std::cout << "Foo(const int &): " << Callable<Foo, int const &>::value << std::endl
<< "Foo(int &): " << Callable<Foo, int &>::value << std::endl
;
}
Something like this maybe? It's a bit round about to make it work on VS2010.
template<typename FPtr>
struct function_traits_impl;
template<typename R, typename A1>
struct function_traits_impl<R (*)(A1)>
{
typedef A1 arg1_type;
};
template<typename R, typename C, typename A1>
struct function_traits_impl<R (C::*)(A1)>
{
typedef A1 arg1_type;
};
template<typename R, typename C, typename A1>
struct function_traits_impl<R (C::*)(A1) const>
{
typedef A1 arg1_type;
};
template<typename T>
typename function_traits_impl<T>::arg1_type arg1_type_helper(T);
template<typename F>
struct function_traits
{
typedef decltype(arg1_type_helper(&F::operator())) arg1_type;
};
template<typename F, typename Arg>
struct is_callable : public std::is_same<typename function_traits<F>::arg1_type, const Arg&>
{
}
Here is a possible solution that utilizes an extra test to see if your template is being instantiated with a const T&:
#include <memory>
#include <iostream>
using namespace std;
template<typename F, typename Arg>
struct is_callable {
private:
template<typename>
static char (&test(...))[2];
template<bool, unsigned value>
struct helper {};
template<unsigned value>
struct helper<true, value> {
typedef void *type;
};
template<typename T>
struct is_const_ref {};
template<typename T>
struct is_const_ref<T&> {
static const bool value = false;
};
template<typename T>
struct is_const_ref<const T&> {
static const bool value = true;
};
template<typename UVisitor>
static char test(typename helper<is_const_ref<Arg>::value,
sizeof(std::declval<UVisitor>()(std::declval<Arg>()), 0)>::type);
public:
static const bool value = (sizeof(test<F>(0)) == sizeof(char));
};
struct foo {
void operator()(const int &) {}
};
int main(void)
{
cout << is_callable<foo, int &>::value << "\n";
cout << is_callable<foo, const int &>::value << "\n";
return 0;
}
Ran across this while doing something else, was able to adapt my code to fit. It has the same features (and limitations) as #Xeo, but does not need sizeof trick/enable_if. The default parameter takes the place of needing to do the enable_if to handle template functions. I tested it under g++ 4.7 and clang 3.2 using the same test code Xeo wrote up
#include <type_traits>
#include <functional>
namespace detail {
template<typename T, class Args, class Enable=void>
struct call_exact : std::false_type {};
template<class...Args> struct ARGS { typedef void type; };
template<class T, class ... Args, class C=T>
C * opclass(decltype(std::declval<T>()(std::declval<Args>()...)) (C::*)(Args...)) { }
template<class T, class ... Args, class C=T>
C * opclass(decltype(std::declval<T>()(std::declval<Args>()...)) (C::*)(Args...) const) { }
template<typename T, class ... Args>
struct call_exact<T, ARGS<Args...>,
typename ARGS<
decltype(std::declval<T&>()(std::declval<Args>()...)),
decltype(opclass<T, Args...>(&T::operator()))
>::type
> : std::true_type {};
}
template<class T, class ... Args>
struct Callable : detail::call_exact<T, detail::ARGS<Args...>> { };
template<typename R, typename... FArgs, typename... Args>
struct Callable<R(*)(FArgs...), Args...>
: Callable<std::function<R(FArgs...)>, Args...>{};