Based on my previous question here Variadic template, function as argument
I have ended up with a simple class below, however how do I use std::invoke or some other method to call Tester::test with Tester::simple as argument? The examples provided at http://en.cppreference.com/w/cpp/utility/functional/invoke#Example were not very helpful for me and I tried many different ways of using std::invoke.
class Tester {
public:
template<typename F, typename... Args>
decltype(auto) test(F&& f, Args&&... args) {
return std::forward<F>(f)(std::forward<Args>(args)...);
}
int simple(int i) { return i; }
};
int main()
{
Tester t;
std::cout << t.test(t.simple, 3); // how do you modify this line such that the code compiles?
}
Thanks!
One way is to modify the definition of your test() member function like so:
class Tester {
public:
template<typename F, typename... Args>
decltype(auto) test(F&& f, Args&&... args) {
return std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
}
int simple(int i) { return i; }
};
We can then pass a member function pointer to test(), with the instance on which the method should be called as the second argument, and then the function arguments themselves:
int main()
{
Tester t;
std::cout << t.test(&Tester::simple, t, 3);
}
The reason this works is because std::invoke has a special overload for pointers-to-members, such that
std::invoke(ptr-to-member, instance, args...);
is called as
(instance.*ptr-to-member)(args...);
which is exactly what we want in this case.
Note, that std::invoke is a part of C++ 17. In case if it is not available, one might implement test function so that it accepts a pointer-to-member-function and an instance of a class:
template<typename F, typename T, typename... Args>
decltype(auto) test(F f, T&& t, Args&&... args) {
return (std::forward<T>(t).*f)(std::forward<Args>(args)...);
}
Now test accepts a pointer-to-member-function as a first argument, an instance of a class as a second argument and an arbitrary number of additional arguments.
Then test might be called like:
Tester t;
std::cout << t.test(&Tester::simple, t, 42);
WANDBOX EXAMPLE
Just to mention yet another possibility, you could wrap the member function call in a lambda and capture the instance t. In C++14 we can use the generic lambda for that, so we don't have to specify the parameters explicitly.
#include <iostream>
#include <utility>
class Tester {
public:
template<typename F, typename... Args>
decltype(auto) test(F&& f, Args&&... args) {
return std::forward<F>(f)(std::forward<Args>(args)...);
}
int simple(int i) { return i; }
};
int main()
{
Tester t;
std::cout << t.test([&t] (auto&&... args) { return t.simple(std::forward<decltype(args)>(args)...); }, 3);
}
Related
I would like to create function calling another function and printing its arguments.
It should be compatible with many functions (returning the same result) with many combinations of variables of arguments.
I would like to have something like this:
int fun1(){}
int fun2(int i){}
int fun3(std::string s, int i){}
void execute_and_print(std::function f, ...)
{
///code
}
int main()
{
execute_and_print(&fun1);
execute_and_print(&fun2, 3);
execute_and_print(&fun3,"ff",4);
}
It could print:
executed function with arguments:
executed function with arguments: 3
executed function with arguments: ff, 4
Is it even possible in C++?
In C++17 it is very simple
template <typename F, typename... Args>
void execute_and_print(F f, Args... args)
{
(std::cout << ... << args);
f(args...);
}
Prior to that there is extra ceremony
template <typename F, typename... Args>
void execute_and_print(F f, Args... args)
{
int dummy[] = { (static_cast<void>(std::cout << args), 0)... };
f(args...);
}
It is not foolproof, but any possible errors will be caught at compile time (ie. the code will not compile). It should work file, as long as the provided parameters match those of the called function, and a matching << operator exists for each parameter.
template<class Fn, class...Args>
void execute_and_print(Fn fn, Args...args) {
int f[sizeof...(Args)] = { (std::cout << args << ", ", 0)... };
fn(args...);
}
Refer to https://en.cppreference.com/w/cpp/language/parameter_pack. The sizeof... command is actually the number of elements, not their combined size.
You can use templates to get it done,
template <class... Args>
void RunThrough(Args&& ... args)
{
([&](auto& input)
{
std::cout << input << ", ";
} (args), ...);
}
template<class Func, class... Args>
decltype(auto) execute_and_print(Func f, Args&&... args)
{
f(args...);
std::cout << "executed function with arguments: ";
RunThrough(args...);
std::cout << std::endl;
}
You can use lambdas, std::function objects and function pointers in this.
Reference: https://stackoverflow.com/a/60136761/11228029
I am in search of a ::std::function usable in constexpr.
Use case: I have a function which takes a function pointer as an argument, and a second which passes a lambda to the first function. Both are fully executable at compile time, so I want to constexpr them.
Eg:
template <class _Type>
class ConstexprFunctionPtr
{
private:
using Type = typename ::std::decay<_Type>::type;
const Type function;
public:
constexpr inline
ConstexprFunctionPtr(const Type f)
: function(f)
{ }
template <typename... Types>
constexpr inline
auto
operator() (Types... args)
const {
return function(args... );
}
};
constexpr inline
void
test()
{
ConstexprFunctionPtr<int(int)> test([](int i) -> int {
return i + 1;
});
int i = test(100);
ConstexprFunctionPtr<int(int)> test2([=](int i) -> int {
return i + 1;
});
i = test2(1000);
}
However, this only works because I am converting the lambda to a function pointer, and of course fails with capturing lambdas as showed in the second example. Can anyone give me some pointers on how to do that with capturing lambdas?
This would demonstrate the usecase:
constexpr
void
walkOverObjects(ObjectList d, ConstexprFunctionPtr<void(Object)> fun) {
// for i in d, execute fun
}
constexpr
void
searchObjectX(ObjectList d) {
walkOverObjects(d, /*lambda that searches X*/);
}
Thanks,
jack
Update:
Thanks for pointing out the C++20 solution, however, I want one that works under C++14
So a lot has changed with C++20 --- most importantly, you can now use dynamic memory and virtual functions within constexpr contexts. This makes it entirely possible to build a constexpr version of std::function. Here's a proof-of-concept (it's long and has no copy or move constructors, so please do not use this as-is). It compiles under clang 10, running code here. I've not tried it under other compilers, and it's worth noting that none of the major compilers claim to have a complete implementation of C++-20 at this time.
#include <type_traits>
#include <utility>
#include <functional>
template<typename Ret, typename... Args> struct _function{
constexpr virtual Ret operator()(Args...) const = 0;
constexpr virtual ~_function() = default;
};
template<typename F, typename Ret, typename... Args> struct _function_impl : public _function<Ret,Args...>{
F f;
constexpr Ret operator()(Args... args) const override {
return f(std::forward<Args>(args)...);
}
constexpr _function_impl(F&& f):f(f){}
};
template<typename > struct function;
template<typename Ret, typename... Args> struct function<Ret (Args...)>{
_function<Ret,Args...> *real_f{nullptr};
constexpr Ret operator()(Args... args) const {
return real_f->operator()(std::forward<Args>(args)...);
}
constexpr ~function(){
if (real_f) delete real_f;
}
template<typename F>
constexpr function(F&& f):real_f(new _function_impl<std::decay_t<F>,Ret,Args...>(std::move(f))){}
};
template<typename Ret, typename... Args>
constexpr Ret call_f_2(const function<Ret(Args...)> &f, Args... a){
return f(std::forward<Args>(a)...);
}
template<typename F, typename... Args>
constexpr decltype(auto) call_f(F && f, Args&&... a){
using Ret = std::invoke_result_t<std::decay_t<F>,Args...>;
function<Ret(Args...)> f2 = std::move(f);
return call_f_2<Ret,Args...>(f2,a...);
}
int main(){
constexpr int c = 3;
constexpr int i = call_f([c](int j) constexpr {return c + j;},4);
return i;
}
I am in search of a ::std::function usable in constexpr
Stop right here. it's impossible. std::function is a polymorphic wrapper function. stateless lambdas, statefull lambdas, functors, function pointers, function references - all of them can build a valid std::function that can change during runtime. so making a compile time equivalent is just a waste of time.
If you just want a compile time generic function parameter, you can just use templates
template<class functor_type>
class my_generic_function_consumer_class{
using decayed_function_type = typename std::decay_t<functor_type>;
decayed_function_type m_functor;
};
In your code in question, just accept a generic functor, and validate it using static_assert:
template<class function_type>
constexpr void walkOverObjects(ObjectList d, function_type&& fun) {
static_assert(std::is_constructible_v<std::function<void(ObjectList), function_type>>,
"function_type given to walkOverObjects is invalid.");
}
I want to create a wrapper class which is able to call member functions (of any type) of the wrapped class with help of templates. This is what I have so far:
template <typename T>
class wrapper {
public:
template<typename R, R (T::*func)()>
void call_func() {
(wrapped.*func)();
}
private:
T wrapped;
};
class some_class {
private:
int i = 2;
public:
void some_func() {
std::cout << i << std::endl;
}
};
int main() {
wrapper<some_class> wr;
// How I need to call at the moment:
wr.call_func<void, &some_class::some_func>();
// How I want call:
wr.call_func<&some_class::some_func>();
return 0;
}
As you can see in the comments of the main function, I want to call the wrapper-function without explicitly specifying the return type of the wrapped member function. (How) Can this be done in C++11?
template<typename F>
void call_func(F func) {
(wrapped.*func)();
}
then call like this:
wr.call_func(&some_class::some_func);
If you want to use the return value too, you'll need this:
template<typename F>
auto call_func(F func) -> decltype((std::declval<T>().*func)()) {
return (wrapped.*func)();
}
If you have C++14, you can omit the -> decltype(...) part and use decltype(auto) as the return value.
If you also want to pass functions, you can use variadic templates and forwarding for that.
template<typename F, typename... Args>
decltype(auto) call_func(F func, Args&&... args) {
return (wrapped.*func)(std::forward<Args>(args)...);
}
You can directly use std::function
For more information on std::function see: http://en.cppreference.com/w/cpp/utility/functional/function
How the compiler interpret the symbol _1, and how the binding take place?
Consider the following example:
class A {
public:
boost::function<void (int x)> g;
};
class B {
public:
B() {}
static void foo(int i) { cout << "Hack: " << i <<endl; }
};
int main() {
A a;
a.g = boost::bind(B::foo,_1);
a.g(2);
return 0;
}
What magic happens internally in the line boost::bind(B::foo,_1);?
And how _1 is maped to the argument passed in the next line a.g(2);?
Output: Hack: 2
I will explain to the best of my ability. First and foremost, _1 is nothing but a global variable. There is nothing special about it in this regard, and it could be named anything else as well - placeholder1, or SergeyA. However, name like _1 is short, has well-understood meaning, and begins with _, which reduces likelihood of it clashing with other global names in the program.
The magic is in the type of this variable. It has a special type, which is reflected in generated bind* object. Later, when operator() is called, the type is recognized to take an argument from operator() arguments.
Here is some illustrating C++-like pseudocode, which is not correct, but is illustrative:
template<class F, class... ARG>
struct bound {
bound(F f, ARGS&&... args) : bound_args(args...), functor(f) { }
std::tuple<ARG...> bound_args;
template<class... T>
void operator()(T&&... args);
F f;
};
template<class F, class... T>
auto bind(F f, T&& args) {
return bound<std::remove_reference_t<T>...>(f, args...);
}
Now, let's introduce a placeholder type.
template<size_t N>
struct placeholder {
enum { position = N; };
template<class...T>
auto operator()(T&&... args) {
return std::get<position>(std::make_tuple(arg...));
}
};
placeholder<0> _1;
placeholder<1> _2;
So far so good. Now, let's see how the operator() actually works on bound object:
template<class... BOUND_ARGS>
template<class... CALL_ARGS>
void bound_object<BOUND_ARGS...>::operator() (CALL_ARGS&&... args) {
call_impl(args..., make_index_sequence<sizeof...(BOUND_ARGS)>{});
}
make_index_sequence here is needed to extract tuple values into function arguments, so do not pay too much attention to it. And here is call_impl;
template<class... BOUND_ARGS>
template<class... CALL_ARGS, size_t... ix>
void bound_object<BOUND_ARGS...>::call_impl(CALL_ARGS&&... args, std::index_sequence<ix...>) {
f(to_arg().(std::get<ix>(bound_args), args...)...);
}
And the last piece of puzzle is to_arg:
template<class B, class... ARGS>
auto to_arg(B&& b, ARGS... args) {
return b;
}
template<class... ARGS>
auto to_arg(placeholder<0> p, ARGS&&... args) {
return p(args);
}
template<class... ARGS>
auto to_arg(placeholder<1> p, ARGS&&... args) {
return p(args);
}
The whole of to_arg here is to give you either the bound argument or one of the supplied arguments, based on the bound argument type. In my example above, I used 3 overloads since you can partially specialize a function, but of course, it would make more sense to put it in a class and partially specialize the class.
In relation with this question, that perhaps is too much oversimplified, I give here a more complex example. The problem that I pretend is depicted with the following code:
// test3.cpp
using namespace std;
template<typename T>
struct exer
{
template<typename R, typename... rArgs, typename... pArgs>
R operator()(R(T::*f)(rArgs...), pArgs&&... args)
{
return (t.*f)(forward<pArgs>(args)...);
}
T t;
};
struct A
{
int addition() { return 0; }
template<typename... Args>
int addition(int a, Args... args) { return a + addition(args...); }
};
struct B
{
public:
template<typename... Args>
int addition(Args&&... args)
{
return m_e(&A::addition, forward<Args>(args)...);
}
private:
exer<A> m_e;
};
int main()
{
B b;
cout << b.addition(1, 2, 3, 4) << endl;
}
This problem here is, in the instantation of B::addition, the type of &A::addition isn't known because different overloads exists. Moreover, B::addition doesn't know also which overload must be used. This doesn't know the compiler until the function is called. But, in order to correctly specify wich overload must be used in exer<A>::operator(), I need to make a casting of &A::addition to cast it to the correct overload.
How can I extract the type of the correct overload of the target function?
Change the question. If you can make exer take a callable object instead of a pointer to member function, like so:
template<typename T>
struct exer
{
T t;
template<typename F, typename... pArgs>
auto operator()(F f, pArgs&&... args)
-> decltype(f(t, forward<pArgs>(args)...))
{
return f(t, forward<pArgs>(args)...);
}
};
Then you can do this instead:
struct B
{
public:
template<typename... Args>
int addition(Args&&... args)
{
struct Invoker {
auto operator()(A& a, Args&&... args) const
->decltype(a.addition(std::forward<Args>(args)...))
{ return a.addition(std::forward<Args>(args)...); }
};
return m_e(Invoker(), forward<Args>(args)...);
}
private:
exer<A> m_e;
};
Now selecting the correct A::addition is done by the compiler using the normal overload resolution rules.
Instead of Invoker you could use a lambda expression, which reduces some of the repetition:
return m_e( [](A& a, Args&&... as) {
return a.addition(forward<Args>(as)...);
},
forward<Args>(args)...);