Passing member function pointer as template parameter - c++

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

Related

How to identify if a method of underlying type held by a shared_ptr can be invoked with one or no parameters at compile time

Using C++ 17. I have the following:
template <typename T>
using ptr_t = std::shared_ptr<const T>;
class some_type;
class A { some_type foo() const; }
class B { some_type foo() const; }
class C { some_type foo(int) const; }
std::variant<ptr_t<A>, ptr_t<B>, ptr_t<C>>;
A variant holds shared_ptr(s) to different types. All expected to have function foo() that may be void or take a parameter. I will then have a visitor that would correctly dispatch foo, something like this (conceptually):
struct visitor
{
template <typename T>
ptr_t<some_type> operator()(const T& config) const
{
if constexpr (// determine if foo() of the underlying type of a shared_ptr can be called with int param)
return config->foo(15);
else
return config->foo();
}
is there a way to say this? I tried various ways but can't come with something that compiles. Template parameter, T, is ptr_t<A|B|C>.
std::is_invocable_v<Callable, Args...> is the way to go. Unfortunatelly, it will not compile just like that with if constexpr. It will either fail because "there is no operator()() overload", or there is no overload for operator taking Args....
I suggest you add a wrapper class for a callable and use it with a specialized alias template of std::variant instead of writing your own visitor. It will allow you to use std::visit seamlessly.
#include <type_traits>
#include <variant>
template <typename Callable>
class wrapped_callable
{
Callable c;
public:
wrapped_callable(Callable c)
: c(c)
{}
template <typename ... Args>
constexpr decltype(auto) operator()(Args &&... args) const
{
return _invoke(std::is_invocable<Callable, Args...>{}, c, std::forward<Args>(args)...);
}
private:
using _invocable = std::true_type;
using _non_invocable = std::false_type;
template <typename T, typename ... Args>
constexpr static decltype(auto) _invoke(_invocable, const T& t, Args &&... args)
{
return t(std::forward<Args>(args)...);
}
template <typename T, typename ... Args>
constexpr static decltype(auto) _invoke(_non_invocable, const T& t, Args ... args)
{
return t();
}
};
template <typename ... T>
using variant_callable = std::variant<wrapped_callable<T>...>;
struct int_callable
{
int operator()(int i) const
{
return i;
}
};
struct non_callable
{
int operator()() const
{
return 42;
}
};
#include <iostream>
int main()
{
using variant_t = variant_callable<int_callable, non_callable>;
// 23 is ignored, 42 is printed
std::visit([](const auto &callable){
std::cout << callable(23) << '\n';
}, variant_t{non_callable()});
// 23 is passed along and printed
std::visit([](const auto &callable){
std::cout << callable(23) << '\n';
}, variant_t{int_callable()});
}
Program returned: 0
42
23
https://godbolt.org/z/e6GzvW6n6
But The idea is not to have any specialization for all types in a variant as it will then require changing the visitor code every time a new type is added.
That is what template alias of std::variant<wrapped_callable<T>...> for. You just add append a new type to the list, that's it.
Take notice, that it does not depend on if constexpr. So if you manage to provide your own variant and is_invocable_v, it will work for C++14. For C++11 possibly, but some modifications regarding constexpr functions might be needed.
Of course you can implement your visitor in the same manner if you want to use std::shared_ptr istead of a callable.
But I don't see any reason to use:
visitor + smart pointer. Just use a smart pointer - it will give you runtime polymorphism in a "classic" way (via virtual inheritence)
why std::shared_ptr? Do you really need to share the ownership? Just stick with std::unique_ptr

How to call a generic std::function with a list of void* parameters?

I have a std::map where I store some arbitrary methods that I want to call later.
map<string, function<void(void)>> methods;
template<typename R, typename ...P>
void storeMethod(const string& name, const function<R(P...)>& method) {
methods[name] = method;
}
A the time of calling, I get the parameters to call the method with in a vector<void*>, where the first element is a pointer where I will store the return value.
How do I automatically cast these parameters to the corresponding types of the method I want to call?
Should I store the types in some way maybe?
void callMethod(const string& name, vector<void*> parameters) {
auto method = methods[name];
// How to call 'method' with all the parameters casted to the required types?
}
For example, if I orignally called storeMethod() with a function<int(string a, float b)>, I need a generic way to call it in callMethod() like this:
*((int*)parameters[0]) = method(*((string*)parameters[1]), *((float*)parameters[2]));
You will have to wrap method in something that can remember the parameter types.
struct OpaqueFunction {
virtual std::any call(const std::vector<std::any> &) = 0;
};
template <typename R, typename ... Args>
struct OpaqueFunctionImpl : OpaqueFunction {
OpaqueFunctionImpl(std::function<R(Args...)> f) : f(std::move(f)) {}
std::any call(const std::vector<std::any> & parameters) override {
return call_impl(parameters, std::index_sequence_for<Args...>{});
}
private:
template <size_t... I>
std::any call_impl(const std::vector<std::any> & parameters, std::index_sequence<I...>) {
return f(std::any_cast<Args>(parameters.at(I))...);
}
std::function<R(Args...)> f;
};
class Methods {
std::map<std::string, std::unique_ptr<OpaqueFunction>> methods;
public:
template<typename R, typename ... Args>
void storeMethod(std::string name, std::function<R(Args...)> method) {
methods[std::move(name)] = std::make_unique<OpaqueFunctionImpl<R, Args...>>(std::move(method));
}
template<typename R>
R callMethod(const std::string & name, const std::vector<std::any> & parameters) {
return std::any_cast<R>(methods.at(name)->call(parameters));
}
};
You can create a Callable type to functions that take different types of arguments and then, store that in a vector (using vector here for simplicity):
struct Callable {
Callable(std::function<void()> f) : zero_(std::move(f)) {}
Callable(std::function<void(int)> f) : one_(std::move(f)) {}
void operator()() { zero_(); }
void operator()(int x) { one_(x); }
std::function<void()> zero_;
std::function<void(int)> one_;
};
//vector of methods
std::vector<Callable> methods;
To store a method, you can either use a template-ized function or just use overloads. I am using overloads here:
void addMethod(std::function<void()> func)
{
methods.push_back(Callable(func));
}
void addMethod(std::function<void(int)> func)
{
methods.push_back(Callable(func));
}
And then to finally call a function:
template<typename ...Args>
void callMethod(int idx, Args ...args) {
auto method = methods[idx];
method(std::forward<Args>(args)...);
}
Main:
int main()
{
addMethod([](int x){
std::cout << "I am function(int)" << x << '\n';
});
addMethod([](){
std::cout << "I am just function()\n";
});
callMethod(0, 200);
callMethod(1);
}
This is the simplest possible way I can think of to achieve this. Their might be better ways and I am really curious about them.
Try it out here: https://godbolt.org/z/HS5a7p

Calling a variadic template function with a member function

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);
}

Variadic members in non-template class

I'm trying to write a class Invocation which has a templated constructor:
template<typename F>
class Invocation {
public:
template<typename... Args>
Invocation(F&& f, Args&&... args)
{ /* store f and args somewhere for later use */ }
...
};
Normally I would parameterize the Invocation class itself with both F and Args..., but in this case I need a uniform type for a given F, so I'm trying to find a way to store args... of any types inside a Invocation<F>, and to incur as little performance hit as possible. (This might not be the best design, but it can be an interesting exercise.)
One thought is to use virtual functions:
template<typename F>
class ArgsBase {
public:
// discard return value
virtual void invoke(F&& f) = 0;
};
template<typename F, typename... Ts>
class Args : public ArgsBase<F> {
public:
Args(Ts&&... args) : args_(std::forward<Ts>(args)...) {}
void invoke(F&& f) override
{
/* somehow call f with args_ (something like std::apply) */
...
}
private:
std::tuple<Ts&&...> args_;
};
And then in the Invocation<F> class, we can for example have an std::unique_ptr<ArgsBase<F>> member, which points to an Args<F, Ts...> object created in the Invocation<F> ctor. And we can call its invoke virtual method when needed.
This is just one random idea I came up with. Is there any other way to achieve this? Ideally without the overhead of virtual functions or anything like that?
UPDATE: Thanks to the comments/answers that suggest using std::function or lambdas. I should've made it clear that I'm actually interested in a more general case, i.e., the variadic stuff might not be arguments to a callable. It can be just anything that I want to store in a class whose type is not parameterized by the types of these stuff.
As mentioned in comment, I wouldn't worry about storing arguments by value. The compiler's copy-elision can be generous.
Particularly if you offer the class an r-value invoke:
#include <tuple>
template<typename F>
class ArgsBase {
public:
// discard return value
virtual void invoke(F&& f) const & = 0;
virtual void invoke(F&& f) && = 0;
};
template<typename F, class... FunctionArgs>
class Args : public ArgsBase<F> {
public:
template<class...Ts>
Args(Ts&&... args) : args_(std::forward<Ts>(args)...) {}
template<std::size_t...Is, class Tuple>
static void invoke_impl(F& f, std::index_sequence<Is...>, Tuple&& t)
{
f(std::get<Is>(std::forward<Tuple>(t))...);
}
void invoke(F&& f) const & override
{
invoke_impl(f,
std::make_index_sequence<std::tuple_size<tuple_type>::value>(),
args_);
/* somehow call f with args_ (something like std::apply) */
}
void invoke(F&& f) && override
{
invoke_impl(f,
std::make_index_sequence<std::tuple_size<tuple_type>::value>(),
std::move(args_));
/* somehow call f with args_ (something like std::apply) */
}
private:
using tuple_type = std::tuple<FunctionArgs...>;
tuple_type args_;
};
template<class Callable, class...MyArgs>
auto later(MyArgs&&...args) {
return Args<Callable, std::decay_t<MyArgs>...>(std::forward<MyArgs>(args)...);
}
void foo(const std::string&, std::string)
{
}
int main()
{
auto l = later<decltype(&foo)>(std::string("hello"), std::string("world"));
l.invoke(foo);
std::move(l).invoke(foo);
}
If you're trying to save a function call with its parameters for later invocation, you could use lambdas packaged in std::function objects:
template<typename F, typename ... Args>
std::function<void()> createInvocation(F f, const Args& ... args)
{
return [f,args...]() { f(args...); };
}
Then you could use it like this:
void myFunc(int a, int b)
{
std::cout << "Invoked: " << a + b << std::endl;
}
int main() {
auto invocation = createInvocation(myFunc, 1, 2);
invocation();
return 0;
}
UPDATE: If you wanted to create a generic non-templated container type, you can wrap a tuple into a type that itself derives from a non-templated type. The main problem then is accessing the underlying data. This can be solved by creating a static function dispatch table that for a given tuple type, redirects queries so that std::get, which requires a compile-time constant index template parameter, can instead be invoked with a dynamically provided function parameter. Here is an implementation that achieves this:
class GenericTupleContainer
{
public:
virtual const void* getItemAtIndex(size_t index) = 0;
};
template<typename ... T>
class TupleContainer : public GenericTupleContainer
{
public:
TupleContainer(T&& ... args)
: data(std::forward<T>(args)...)
{}
const void* getItemAtIndex(size_t index) override
{
if(index >= sizeof...(T))
throw std::runtime_error("Invalid index");
return dispatchTable[index](data);
}
private:
template<size_t index>
static const void* getItemAtIdx(const std::tuple<T...>& data)
{
return &std::get<index>(data);
}
using GetterFn = const void*(*)(const std::tuple<T...>&);
static GetterFn* initDispatchTable()
{
static GetterFn dispatchTable[sizeof...(T)];
populateDispatchTable<sizeof...(T)>(dispatchTable, std::integral_constant<bool, sizeof...(T) == 0>());
return dispatchTable;
}
static GetterFn* dispatchTable;
template<size_t idx>
static void populateDispatchTable(GetterFn* table, std::false_type);
template<size_t idx>
static void populateDispatchTable(GetterFn* table, std::true_type)
{
//terminating call - do nothing
}
std::tuple<T...> data;
};
template<typename ... T>
typename TupleContainer<T...>::GetterFn* TupleContainer<T...>::dispatchTable = TupleContainer<T...>::initDispatchTable();
template<typename ... T>
template<size_t idx>
void TupleContainer<T...>::populateDispatchTable(GetterFn* table, std::false_type)
{
table[idx-1] = &TupleContainer<T...>::template getItemAtIdx<idx-1>;
populateDispatchTable<idx-1>(table, std::integral_constant<bool, idx-1 == 0>() );
}
template<typename ... T>
auto createTupleContainer(T&& ... args)
{
return new TupleContainer<T...>(std::forward<T>(args)...);
}
Then you can use the above as follows:
int main() {
GenericTupleContainer* data = createTupleContainer(1, 2.0, "Hello");
std::cout << *(static_cast<const int*>(data->getItemAtIndex(0))) << std::endl;
std::cout << *(static_cast<const double*>(data->getItemAtIndex(1))) << std::endl;
std::cout << (static_cast<const char*>(data->getItemAtIndex(2))) << std::endl;
return 0;
}
As you can see from the above usage, you've achieved the aim of wrapping an arbitrary templated tuple into a non-templated type, in such a way that you can access the component members with a normal (function) index parameter instead of a template one. Now the return type of such a getter has to be universal, so I've chosen to use void* here, which is not ideal. But you can develop this idea to make this container give more useful information about the types of its data tuple members. Also, note that this does use a virtual function. With some further work you can get rid of this as well, although you won't be able to get rid of at least one function pointer lookup (i.e. the lookup in the dispatch table) - this is the price paid for gaining the flexibility of being able to use a runtime value to index into the tuple.

Avoiding explicit functor template type

I'm playing with functors. I'm using the standard example below:
class C {
public:
template <typename Func>
void foo(Func fun)
{
fun();
}
};
struct S {
void operator()() { printf ("in S\n"); }
};
....
C myClass;
myClass.foo (S());
This works nicely and I don't need to explicitly provide the S template type in the call to foo(), it just figures it out. But suppose I want to store the functor as a member variable and call it later:
class C {
public:
template <typename Func>
void foo(Func fun) {
_myFunc = fun;
}
void someOtherThing() {
_myFunc();
}
private:
WHAT_IS_THIS_TYPE _myFunc;
};
Do I now need to make the whole class a template? If so, can the compiler infer the template type as it did with the single functor, or must I provide it explicitly? Thanks.
You can use std::function (in C++11) or boost::function to store callable objects (functions, functors). It implements type erasure pattern.
class C {
public:
template <typename Func>
void foo(Func fun) {
_myFunc = fun;
}
void someOtherThing() {
_myFunc();
}
private:
std::function<void()> _myFunc;
};
Here's a hand-made way to avoid making class C a template:
struct C {
template <typename Func>
void foo(Func fun) {
_myFunc = static_cast <void*>(&fun);
stub = call <Func>;
}
void someOtherThing() {
stub(_myFunc);
}
private:
void* _myFunc;
void (*stub)(void*);
template <typename F>
static void call(void* f) {
(*static_cast <F*>(f))();
}
};
struct S {
void operator()() { std::cout << "in S" << std::endl; }
};
int main()
{
S s;
C myClass;
myClass.foo(s);
myClass.someOtherThing();
}
When you call foo(), type Func is "stored" inside the template static function call, a pointer to (an instatiation of) which is stored in stub. The latter is called by someOtherThing to actually invoke _myFunc, which is nothing but plain void*. For this to happen, _myFunc is first cast back to the correct type, which is only known inside call's body.
The only catch is that using pointers to functions there can be no inlining for stub(...) call.