I have a class:
template <typename ...Arguments>
class CSignalConnection
{
public:
CSignalConnection(std::function<void(Arguments...)> target) : m_target(target) {}
void invoke(Arguments&&... args) const
{
m_target(std::forward<Arguments>(args)...);
}
private:
std::function<void(Arguments...)> m_target;
};
I want to be able to declare CSignalConnection<void> and call invoke with no arguments. And I want to avoid specializing, i. e. duplicating the whole class, when I only have a couple void-incompatible methods (like invoke here which should be declared with 0 arguments). I have a couple more classes like this so I hate to write everything twice (and edit in two places).
One idea I have is to write both void and non-void invoke overloads and disable one with SFINAE, but I don't know how to actually implement this.
Using CSignalConnection<> will make the Arguments pack empty. The following works for me
void f() {
std::cout << "hello world\n";
}
int main () { {
CSignalConnection<> cs{&f};
cs.invoke();
}
However, since you have no type deduction this is a misuse of forwarding, you'll need to make invoke() deduce the types of its arguments to get real universal references (forwarding references)
template <typename ...Arguments>
class CSignalConnection {
public:
template <typename... Ts>
void invoke(Ts&&... args) const
{
m_target(std::forward<Ts>(args)...);
}
//... rest of the class omitted ...
};
Related
I have created some code that uses a function template and an overload (not a specialization) of that function. When I call the function with an object of a class that is derived from the parameter in the it uses the template resulting in a compile error. I have been reading http://www.gotw.ca/publications/mill17.htm
and I had the impression that overloaded functions would always have preference above templates. I have created a similar do-nothing example:
class ITest
{
public:
virtual void foo()=0;
};
class TheTest:public ITest
{
public:
virtual void foo()
{
}
};
class test
{
public:
template<typename T>
void handle(T par)
{
par++;
}
void handle(ITest &t)
{
t.foo();
}
};
void TestThem()
{
test t;
t.handle(2);
t.handle(3.0);
TheTest t2;
t.handle(t2);
}
I would expect t.handle(t2) to call the overloaded void handle(ITest &t) since TheTest is derived from ITest. However the compiler selects the template which generates an error.
When I change void handle(ITest &t) to void handle(TheTest &t) it compiles fine.
I fixed it by removing the template function and overloading for all used types, but this is cumbersome since they all do exactly the same thing.
I had the impression that overloaded functions would always have preference above templates.
This is true, but only when the non template function and template function are equally good. In that case the non template function is used.
In this case though they are not both equally good. t2 is a TheTest, when overload resolution runs it finds void handle(ITest &t) and void handle(TheTest par) (I've instantiated the template here). Sine the template version will give an exact match it is a better function and is chosen.
The way to fix this is to constrain the template to only work for types that aren't derived from ITest. If you change the template function to
template<typename T, std::enable_if_t<!std::is_base_of_v<ITest, T>, bool> = true>
void handle(T par)
{
par++;
}
Then it will only be called for types that don't derive from ITest. You can see it working in this live example.
I'm trying to create a variadic template class that looks like this :
template <class... Args>
class Message
{
private:
std::function<void(Args...)> _function;
public:
//stuff
};
I want to have an option to bind so the user can bind any function (with corresponding arguments) when he wants. I've tried this approach (this function is a part of the Message class, so Args... comes from the template argument of the class):
template<class T>
void Message::bindFunction(void(T::*function)(Args... args), T* ownerPtr)
{
//This doesn't work
_function = boost::bind(function,args, ownerPtr);
}
However the above doesn't work, I've tried to create the tuple from the args in the bind function, but the compiler keeps saying:
<args_0> undeclared identifier.
(If I pass more arguments it changes)
From the user's point of view it should look like this:
class Foo
{
public:
void test2(int a, float b, double c)
{
std::cout << "bla";
}
};
int main()
{
Foo f;
Message<int,float,double> Mess;
Mess.bindFunction(&Foo::test2, &f);
}
I've seen a lot of articles talking about forwarding the parameters, however most of the answers confuse me more than I am already with different template structures without explaining them.
Use a lambda because they're much nicer (Live Demo (C++11)):
template<class T>
void bindFunction(void(T::*function)(Args...), T* ownerPtr)
{
_function = [function, ownerPtr](Args... args)
{
(ownerPtr->*function)(args...);
};
}
We are capturing the function pointer and pointer to instance of the class with [function, ownerPtr] in the lambda declaration.
The lambda accepts a list of arguments whose types are specified in the variadic template for the Message class: Args... args.
Internally we call the function using our instance with the (ownerPtr->*function) syntax, and then pass in the arguments by expanding the parameter pack (args...)
To call the function you might write something like this:
void callFunction(Args&&... args)
{
_function(std::forward<Args>(args)...);
}
We use perfect forwarding to pass our arguments to the std::function<void(Args...)> member.
I have a base class MessageBase, from which I derive various other message classes, e.g., MessageDerived. I have another class that does some processing on various types of data, including a catchall method template:
struct Process {
void f(int a);
void f(const char* b);
template<typename T> void f(const T &t) { ... }
};
So if I call Process::f on a message object, the template method is called.
Now I want to add custom functionality for for my message classes. I am not allowed to change Process, so I want to derive from it (but even if I could change it, I can't find a way to get the custom functionality). I tried:
struct ProcessDerived : public Process {
void f(const MesaageBase& m) { ... } // Custom functionality for messages.
};
But that only works when I call ProcessDerived::f on a MessageBase object. If I invoke it on a MessageDerived object, the template method gets selected instead.
Is there a way to get the custom function selected on all message classes while letting the template catch all other types?
You need to use SFINAE here. Here is an example (note that it needs c++11 to work):
struct ProcessDerived : public Process
{
template<typename T> void f(const T &t, typename std::conditional<std::is_base_of<MessageBase, T>::value, int, void>::type = 0)
{
/// do something specific
}
template<typename T> void f(const T &t, ...)
{
return Process::f (t);
}
};
};
You can read more about it at http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error
ProcessDerived::f shadows all definitions of Process::f (see here: Overloading rules for inheritance in C++). So calling ProcessDerived::f with a MessageDerived object calls ProcessDerived::f(const MessageBase&) as this is the only visible f, but e.g.
ProcessDerived pd;
pd(42);
won't compile. You need to add a
using Process::f;
in ProcessDerived for the problem you described showing up. The solution proposed by Alex Telishev while I was writing fixes both problems at once, however.
I have some function templates, for example
template <typename T>
void foo(T);
template <typename T>
void bar(T);
// others
and I need to pass each one to an algorithm that will call it with various types, e.g.
template <typename F>
void some_algorithm(F f)
{
// call f with argument of type int
// call f with argument of type SomeClass
// etc.
}
I can't pass in my function template uninstantiated, but I can't instantiate it with any specific type either because some_algorithm will need to call it with arguments of several different types.
I could adapt my function templates to be polymorphic function objects, e.g.
struct foo_polymorphic
{
template <typename T>
void operator()(T t)
{
foo(t);
}
};
and then pass it as some_algorithm(foo_polymorphic()). But this requires writing a separate adapter for each of my function templates.
Is there a generic way of adapting a function template to be a polymorphic function object, i.e. some mechanism that I can re-use for each of the function templates I need to adapt, without having to declare something separately for each one?
The short version of the problem is given an overloaded name f, how to concisely write an object ff such that ff(a0, a1, a2, ...) ultimately calls f(a0, a1, a2, ...).
A polymorphic functor, how you point out yourself, is the usual solution. But it must be defined out of line (since it has a template member), so I'll consder that not concise enough for the purposes of my answer.
Currently lambda expressions yield a monomorphic functor, so they're close but not quite there.
// set of functions overloaded on int and double
void f(int);
void f(double);
auto ff = [](int i) { return f(i); };
As GMan pointed out in the comments polymorphic lambdas would (should?) be the solution to concisely write polymorphic functors inline.
In the meantime, it is possible to write a make_overload helper that combines multiple functors into one, such that
auto ff = make_overload(
[](int arg0) { return f(arg0); }
, [](double arg0) { return f(arg0); } );
would 'capture' the whole overload set. Perhaps a Boost.Preprocessor macro could help here, so that auto ff = POLYMORPHIC_LAMBDA( 1, (int)(double), { return f(arg0); } ); be used inline. I suspect there are arity restrictions however (hence the first macro argument), unlike the usual out-of-line hand-written polymorphic functor solution; so this wouldn't help with e.g. variadic function templates.
Why couldn't you use template template parameters? You said you can't pass your template uninstantiated, but I'm not sure if you've heard of this before, tell me if you have and it won't work.
I don't know what your code structure looks like, but can you do something like
I know this works, don't know if it's what yo uwant though:
template<typename T>
T some_algorithm(T data) { return T(); } // just returning nothing for example
template<typename T, T(*Something)(T)>
class FuncClass {
public:
T run(T data) { return Something(data); }
};
template<typename T, typename Functor>
void apply_algorithm(T data) {
Functor F;
F.run(data);
}
int main() {
int mydata = 4;
apply_algorithm<int, FuncClass<int, some_algorithm<int> > >(mydata);
cin.get();
}
I am trying to write a code that calls a class method given as template parameter. To simplify, you can suppose the method has a single parameter (of an arbitrary type) and returns void. The goal is to avoid boilerplate in the calling site by not typing the parameter type. Here is a code sample:
template <class Method> class WrapMethod {
public:
template <class Object>
Param* getParam() { return ¶m_; }
Run(Object* obj) { (object->*method_)(param_); }
private:
typedef typename boost::mpl::at_c<boost::function_types::parameter_types<Method>, 1>::type Param;
Method method_;
Param param_
};
Now, in the calling site, I can use the method without ever writing the type of the parameter.
Foo foo;
WrapMethod<BOOST_TYPEOF(&Foo::Bar)> foo_bar;
foo_bar.GetParam()->FillWithSomething();
foo_bar.Run(foo);
So, this code works, and is almost what I want. The only problem is that I want to get rid of the BOOST_TYPEOF macro call in the calling site. I would like to be able to write something like WrapMethod<Foo::Bar> foo_bar instead of WrapMethod<BOOST_TYPEOF(&Foo::Bar)> foo_bar.
I suspect this is not possible, since there is no way of referring to a method signature other than using the method signature itself (which is a variable for WrapMethod, and something pretty large to type at the calling site) or getting the method pointer and then doing typeof.
Any hints on how to fix these or different approaches on how to avoid typing the parameter type in the calling site are appreciated.
Just to clarify my needs: the solution must not have the typename Param in the calling site. Also, it cannot call FillWithSomething from inside WrapMethod (or similar). Because that method name can change from Param type to Param type, it needs to live in the calling site. The solution I gave satisfies both these constraints, but needs the ugly BOOST_TYPEOF in the calling site (using it inside WrapMethod or other indirection would be fine since that is code my api users won't see as long as it is correct).
Response:
As far as I can say, there is no possible solution. This boil down to the fact that is impossible to write something like WrapMethod<&Foo::Bar>, if the signature of Bar is not known in advance, even though only the cardinality is necessary. More generally, you can't have template parameters that take values (not types) if the type is not fixed. For example, it is impossible to write something like typeof_literal<0>::type which evalutes to int and typeof_literal<&Foo::Bar>::type, which would evaluate to void (Foo*::)(Param) in my example. Notice that neither BOOST_TYPEOF or decltype would help because they need to live in the caling site and can't be buried deeper in the code. The legitimate but invalid syntax below would solve the problem:
template <template<class T> T value> struct typeof_literal {
typedef decltype(T) type;
};
In C++0x, as pointed in the selected response (and in others using BOOST_AUTO), one can use the auto keyword to achieve the same goal in a different way:
template <class T> WrapMethod<T> GetWrapMethod(T) { return WrapMethod<T>(); }
auto foo_bar = GetWrapMethod(&Foo::Bar);
Write it as:
template <typename Object, typename Param, void (Object::*F)(Param)>
class WrapMethod {
public:
Param* getParam() { return ¶m_; }
void Run(Object* obj) { (obj->*F)(param_); }
private:
Param param_;
};
and
Foo foo;
WrapMethod<Foo, Param, &Foo::Bar> foo_bar;
foo_bar.getParam()->FillWithSomething();
foo_bar.Run(foo);
EDIT: Showing a template function allowing to do the same thing without any special template wrappers:
template <typename Foo, typename Param>
void call(Foo& obj, void (Foo::*f)(Param))
{
Param param;
param.FillWithSomthing();
obj.*f(param);
}
and use it as:
Foo foo;
call(foo, &Foo::Bar);
2nd EDIT: Modifying the template function to take the initialization function as a parameter as well:
template <typename Foo, typename Param>
void call(Foo& obj, void (Foo::*f)(Param), void (Param::*init)())
{
Param param;
param.*init();
obj.*f(param);
}
and use it as:
Foo foo;
call(foo, &Foo::Bar, &Param::FillWithSomething);
If your compiler supports decltype, use decltype:
WrapMethod<decltype(&Foo::Bar)> foo_bar;
EDIT: or, if you really want to save typing and have a C++0x compliant compiler:
template <class T> WrapMethod<T> GetWrapMethod(T) { return WrapMethod<T>(); }
auto foo_bar= GetWrapMethod(&Foo::Bar);
EDIT2: Although, really, if you want it to look pretty you either have to expose users to the intricacies of the C++ language or wrap it yourself in a preprocessor macro:
#define WrapMethodBlah(func) WrapMethod<decltype(func)>
Have you considered using method templates?
template <typename T> void method(T & param)
{
//body
}
Now the compiler is able to implicitly determine parameter type
int i;
bool b;
method(i);
method(b);
Or you can provide type explicitly
method<int>(i);
You can provide specializations for different data types
template <> void method<int>(int param)
{
//body
}
When you are already allowing BOOST_TYEPOF(), consider using BOOST_AUTO() with an object generator function to allow type deduction:
template<class Method> WrapMethod<Method> makeWrapMethod(Method mfp) {
return WrapMethod<Method>(mfp);
}
BOOST_AUTO(foo_bar, makeWrapMethod(&Foo::Bar));
Okay let's have a go at this.
First of all, note that template parameter deduction is available (as noted in a couple of answers) with functions.
So, here is an implementation (sort of):
// WARNING: no virtual destructor, memory leaks, etc...
struct Foo
{
void func(int e) { std::cout << e << std::endl; }
};
template <class Object>
struct Wrapper
{
virtual void Run(Object& o) = 0;
};
template <class Object, class Param>
struct Wrap: Wrapper<Object>
{
typedef void (Object::*member_function)(Param);
Wrap(member_function func, Param param): mFunction(func), mParam(param) {}
member_function mFunction;
Param mParam;
virtual void Run(Object& o) { (o.*mFunction)(mParam); }
};
template <class Object, class Param>
Wrap<Object,Param>* makeWrapper(void (Object::*func)(Param), Param p = Param())
{
return new Wrap<Object,Param>(func, p);
}
int main(int argc, char* argv[])
{
Foo foo;
Wrap<Foo,int>* fooW = makeWrapper(&Foo::func);
fooW->mParam = 1;
fooW->Run(foo);
Wrapper<Foo>* fooW2 = makeWrapper(&Foo::func, 1);
fooW2->Run(foo);
return 0;
}
I think that using a base class is the native C++ way of hiding information by type erasure.