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.
Related
I have a bunch of very similar functions:
void foo1(Obj o) {
bar(o.a);
}
void foo2(Obj2 o) {
bar(o.b);
}
void foo3(Obj3 o) {
bar(o.c);
}
How can I reduce the duplicating of code? Can I do something like:
template<typename T, pointerToMember>
void foo(T o) {
bar(o.pointerToMember);
}
And then create all functions like:
foo<Obj, Obj.x>;
...
?
Yes it is possible to have a pointer to member as template parameter:
#include <string>
struct Obj {
int a,b,c;
};
void bar(int x){}
template<typename T, int (T::*pointerToMember)>
void foo(T o) {
bar(o.*pointerToMember);
}
int main() {
Obj x;
foo<Obj,&Obj::a>(x);
}
However, there are different ways that would make the call less verbose. You could pass the member pointer as parameter to be able to deduce it, that would allow to call it as
foo(x,&Obj::a);
Last not least, you could call bar directly
bar(x.a);
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
Given a function that calls a templated function argument and calls another function that does something with the returned value:
template <typename T>
void doSomething(T &&) {
// ...
}
template <typename T_Func>
void call(T_Func &&func) {
doSomething(func());
}
How can this be extended to work with a functor that returns void? Ideally, I would like to add an overloaded void doSomething() { ... } that is called if func's return type is void.
Currently this just results in an error: invalid use of void expression if func returns void.
Working example on Ideone
I think you could create a struct helper to use overloaded , operator more or less like this:
#include <type_traits>
#include <utility>
struct my_void { };
struct my_type { };
template <class T, typename std::enable_if<std::is_void<T>::value>::type* = nullptr>
my_void operator,(T, my_type) { return {}; }
template <class T, typename std::enable_if<!std::is_void<T>::value>::type* = nullptr>
T &&operator,(T &&val, my_type) { return std::forward<T>(val); }
template <typename T>
void doSomething(T &&) {
}
template <typename T_Func>
void call(T_Func &&func) {
doSomething((func(), my_type{}));
}
int main() {
auto func1 = []() -> bool { return true; };
auto func2 = []() -> void { };
call(func1);
call(func2);
}
[live demo]
Edit:
Thanks to Piotr Skotnicki and Holt (they pointed out that the first overload actually wouldn't ever be triggered and proposed simplified version of the approach):
#include <type_traits>
#include <utility>
struct dumb_t { };
template <class T>
T &&operator,(T &&val, dumb_t) { return std::forward<T>(val); }
template <typename T>
void doSomething(T &&) {
}
template <typename T_Func>
void call(T_Func &&func) {
doSomething((func(), dumb_t{}));
}
int main() {
auto func1 = []() -> bool { return true; };
auto func2 = []() -> void { };
call(func1);
call(func2);
}
[live demo]
doSomething() takes a parameter, and a parameter cannot be void.
So, in order for this to work, you also need an overloaded doSomething() that takes no parameters. This is going to be the first step:
template <typename T>
void doSomething(T &&) {
// ...
}
void doSomething()
{
}
So, you're going to have to do this first, before you can even get off the ground.
It's also possible that you would like to supply a default value for the parameter, in case the functor returns a void; and still use a single template. That's another possibility, and the following solution can be easily adjusted, in an obvious way, to handle that.
What needs to happen here is a specialization of call() for a functor that returns a void. Unfortunately, functions cannot be partially specialized, so a helper class is needed:
#include <utility>
template <typename T>
void doSomething(T &&) {
// ...
}
void doSomething()
{
}
// Helper class, default implementation, functor returns a non-void value.
template<typename return_type>
class call_do_something {
public:
template<typename functor>
static void call(functor &&f)
{
doSomething(f());
}
};
// Specialization for a functor that returns a void.
//
// Trivially changed to call the template function instead, with
// a default parameter.
template<>
class call_do_something<void> {
public:
template<typename functor>
static void call(functor &&f)
{
f();
doSomething();
}
};
// The original call() function is just a wrapper, that selects
// the default or the specialized helper class.
template <typename T_Func>
void call(T_Func &&func) {
call_do_something<decltype(func())>::call(std::forward<T_Func>(func));
}
// Example:
void foobar()
{
call([] { return 1; });
call([] {});
}
You can provide an extra pair of overloaded helper functions (named callDispatch in my example below) to dispatch the call as required, which eliminates the need for partial specialisation and thus helper classes. They are overloaded by using different signature specifications for the std::function objects they take (live code here):
#include <iostream>
#include <functional>
int func1()
{
return 1;
}
void func2()
{
}
template <typename T>
void doSomething(T &&)
{
std::cout << "In param version" << std::endl;
// ...
}
void doSomething()
{
std::cout << "In no-param version" << std::endl;
// ...
}
template <typename R, typename ... Args>
void callDispatch(std::function<R(Args...)> &&f)
{
doSomething(f());
}
template <typename ... Args>
void callDispatch(std::function<void(Args...)> &&f)
{
f();
doSomething();
}
template <typename T>
void call(T &&func) {
callDispatch(std::function<std::remove_reference_t<T>>(func));
}
int main() {
call(func1);
call(func2);
}
One lean variant would be to give the method a function as parameter. Then you evaluate the expression inside the method and see if did anything. In general this is usally bad practice, since you usually can infer how it returns stuff and when it is needed.
I have a class template:
template <typename Argument> class Signal
{
void invoke(Argument arg) {}
};
Now I want to invoke signals without parameter (meaning void parameter). I assume I could specialize the whole class for void and it would compile. But there's a lot of code in the class, I don't want to duplicate it. I want to only specialize whatever neccessary. So I try adding:
// void specialization
template<>
void Signal<void>::invoke()
{
}
And get an error:
error C2244: 'Signal::invoke' : unable to match function
definition to an existing declaration
Why is that?
The same code works for any type other than void.
The specialization for this template:
template <typename Argument> class Signal
{
void invoke(Argument arg) {}
};
would be:
template<>
void Signal<void>::invoke(void arg)
{
}
which is illegal because you can't have a void object.
One way of doing what you want is to use overloading to declare both invoke methods, and use some templating tricks (I believe this one is called SFINAE) to only allow the correct overload available based on your class template argument:
template <typename Argument> class Signal
{
public:
static constexpr bool IsVoid = is_same<Argument, void>::value;
template <typename T = Argument, typename = typename std::enable_if< !IsVoid && is_same<Argument, T>::value>::type >
void invoke(T arg) {
// only available for non-void types
}
template <typename T = Argument, typename = typename std::enable_if< IsVoid >::type >
void invoke() {
// only available for void class specialization
}
}
Signal<void> sv;
Signal<int> si;
sv.invoke(); // OK
si.invoke(1); // OK
sv.invoke(1); // NOT OK
sv.invoke("s"); // NOT OK
si.invoke(); // NOT OK
si.invoke("s"); // NOT OK
You can find more about the usage of enable_if here: std::enable_if to conditionally compile a member function, Why should I avoid std::enable_if in function signatures.
What about C++11 variadic templates :
template<typename ...Args>
struct Signal {
typedef std::function<void(Args...)> slot_type;
std::list<slot_type> listeners;
template<typename Callable>
void connect(Callable callable) {
listeners.emplace_back(callable);
}
void invoke(Args... args) {
for(slot_type& slot : listeners)
slot(args...);
}
};
void show_me(const std::string& data, int id) {
std::cout << "hello " << data << " : " << id << std::endl;
}
int main() {
Signal<std::string, int> s;
s.connect(show_me);
s.invoke("world", 42);
// ...
}
It scales well with 0, 1 or more args.
If yo will try to declare a variable
void a;
you also will receive a compile error.
The problem is that compiler expects some type instead of Argument here
template <typename Argument> class Signal
{
void invoke(Argument arg) {}
};
and void is not treated as a type here.
Hi I was playing around with TMP and was thinking of generating of a class
that looks something like:
template<typename T, typename LogFunc>
class
{
(where LogFunc should be defaulted to "nop" function)
Idea is to have a class that defines some functionality for instances of type T, for example checks if the number is even, and also has the option to log by calling
void memberFunc(T& t)
{
LogFunc(t);
}
or maybe
void memberFunc(T& t)
{
LogFunc lf;
lf(t);
}
Can it be done?
From reading A on SO, lambdas are kind of problematic as templ params.
BTW if somebody cares this is what I tried but it prints out
:(
The problem is that the type of a lambda is a compiler-enforced singleton; it has only one value, which is the lambda itself; furthermore, the type has a deleted constructor. So you can't pass lambdas as part of a template instantiation, even with decltype. But there's nothing stopping you from passing them as constructor arguments.
However, here we run into another problem: constructor arguments are not used to deduce a template instantiation (which is why the standard library provides utilities like make_pair and make_tuple). So we need a templatized factory function.
With all that, the solution is pretty simple:
template<typename T, typename LogFunc>
class Foo {
public:
Foo(const T& t, LogFunc fn) : t_(t), lfn_(fn) {}
//...
private:
T t_;
LogFunc lfn_;
};
struct Noop {
template<typename...A>
void operator()(A...) { };
};
template<typename T, typename LogFunc=Noop>
Foo<T, LogFunc> make_foo(const T& t, LogFunc func=LogFunc()) {
return Foo<T, LogFunc>(t, func);
}
This will not answer directly, but gives a number of hints about what you did.
The LogFunc parameter is a type (not an object), hence
LogFunc(t) creates a temporary LogFunc giving t as parameter (you are in fact calling the LogFunc::LogFunc(T&) contructor).
LogFunc lf; lf(t); creates a stack-living default contructed Logfunc, named lf, and lf(t) calls its LogFunc::operator()(T&) member function.
LogFunc()(t) creates a temporary default-constructed LogFUnc and calls operator()(T&) on it.
About lambdas, they are in fact classes whose constructor takes the captured varaibles, and whose operator() takes the parameters you declare. But they exist only "internaly" to the compiler, and don't have a "name" you can refer to.
What you can do is deduce its type with a decltype, or with a free-function.
Typically a parametric functional class stores a frunction object, initialized at construction.
#include <iostream>
template<class Fn>
class LogFunc
{
public:
LogFunc(Fn f) :fn(f) {}
template<class T>
void memberFunc(T& t)
{ fn(t); }
private:
Fn fn;
};
template<class Fn>
LogFunc<Fn> makeLogFunc(Fn f)
{ return LogFunc<Fn>(f); }
int main()
{
int x=5;
auto lf = makeLogFunc([](int& a){ std::cout << a << std::endl; });
lf.memberFunc(x);
return 0;
}
compile as "g++ -pedantic -Wall -std=c++11", and will ouptut
5
The other answers are all fine, but you can also just pass in a constructor argument with a std::function<T>. That looks like this:
#include <functional>
#include <iostream>
template <typename T> void someOther(T val){
std::cout << "used other "<<val<<std::endl;
}
template <typename T> void noop(T val){
std::cout << "noop "<<val<<std::endl;
}
template<typename T>
struct A{
A(std::function<void(T)> f =noop<T> ) : mf(f){}
void memberFunc(T valx){
mf(valx);
}
std::function<void(T)> mf;
};
int main(){
A<int> aNoop; ;
A<float> aSomeOther{someOther<float>} ;
aNoop.memberFunc(5);
aSomeOther.memberFunc(3.55);
}
An alternative is to use functor classes, like this:
#include <iostream>
template <typename T> struct OtherC{
void operator()(T v){ std::cout <<"other "<<v<<std::endl; };
};
template <typename T> struct NoopC{
void operator()(T){ std::cout << "noop"<<std::endl; };
};
template<typename T, template <typename X> class F = NoopC >
struct A{
static void memberFunc(T valx){ F<T>()(valx); }
};
int main(){
A<int> aNoop;
A<float,OtherC> aSomeOther ;
aNoop.memberFunc(5);
aSomeOther.memberFunc(3.55);
}