I'm writing C++ class that interfaces with a library. The library has a bunch of functions that look like the following:
Library.h
int FunctionA(int deviceNumber, ...);
int FunctionB(int deviceNumber, ...);
int FunctionC(int deviceNumber, ...);
int FunctionD(int deviceNumber, ...);
int FunctionE(int deviceNumber, ...);
Each instance of my C++ class has an associated deviceNumber which never changes, so I have deviceNumber stored as a member variable, and every time I call a library function, I pass the member in as the function call's first argument.
This is fine, and there's no real reason for me to change the way it is. But out of curiosity, I was wondering if C++ had any mechanism to "transform" arguments that would let me avoid passing the same argument in every call. The obvious way to accomplish this is to overload everything. Let's say my class is called Foo:
Foo.cpp
int Foo::FunctionA(...) {
// deviceNumber_ is a const member
return ::FunctionA(deviceNumber_, ...);
}
The only problem is that this requires a method for each function call, so as the library grows, it gets more and more annoying without a code generator.
Is there any general way to provide the overloading behaviour without actually overloading the functions? Is there a mechanism in C++ to "expand" an argument into multiple arguments? I'm imagining it would look like:
// These two calls are equivalent
FunctionA(deviceNumber, ...);
FunctionA(Magic(...));
// Magic() expands the arguments, adding deviceNumber
Even if the solution is much uglier and less readable than leaving everything alone, I'm curious if it's possible. After searching around, variadic templates seem to be the closest match, but I can't really wrap my head around how they could be used to accomplish this.
You might be happy with a generic relay function:
Live On Coliru
#include <iostream>
int foo1(int device_number, const char*) { std::cout << __PRETTY_FUNCTION__ << "\n"; return device_number*42; }
double foo2(int device_number) { std::cout << __PRETTY_FUNCTION__ << "\n"; return device_number*3.14159; }
struct facade {
facade(int dn) : device_number(dn) {}
template <typename F, typename... A>
auto call(F&& f, A&&... args) const {
return std::forward<F>(f)(device_number, std::forward<A>(args)...);
}
private:
int device_number;
};
int main() {
facade dev(2);
std::cout << dev.call(foo1, "yes ma'am") << "\n";
std::cout << dev.call(foo2) << "\n";
}
I would probably choose a marco in the cpp file as the easiest solution (strictly in the cpp file though)
Variadic templates could help here too. However it sounds like you are doing something embedded and that might be an issue.
Also, I'm not sure if you mean that each FunctionA is overloaded or FunctionA refers to exactly one function.
Anyway, my template solution will help if there are multiple FunctionAs
template<typename... Args>
int Foo::FunctionA(Args&& ...args) {
return ::FunctionA(deviceNumber_, std::forward<Args>(args)...);
}
I put pseudo code , for C++ type structure.
Class Prototype might be following forms.
class Foo {
private private_member_of_deviceNumber;
....
int FunctionA(...);
....
}
Foo Class constructor will assign deviceNumber to private member variable.
class Foo::Foo(int deviceNumber) {
int private_member_of_deviceNumber = deviceNumber;
}
Foo Class member FunctionA(...) will like this form.
int Foo::FunctionA(...) {
return ::FunctionA( private_member_of_deviceNumber , ...);
}
How about like this way?
Related
I'm creating a class called MessageableObject, that can register its own member functions in a map. These functions can be called from outside by calling sendMessage, providing a return type as a template parameter, and passing the name of the function, as well as the paramters as variadic arguments. I've seen something very similar to this done before, only the functions were not member functions of the class storing them.
Below is the code I've written thus far, as well as a test case that should succeed.
#include <iostream>
#include <typeindex>
#include <typeinfo>
#include <unordered_map>
class MessageableObject
{
using _message_ptr = void(MessageableObject::*)(void);
std::unordered_map<const char*, std::pair<_message_ptr, std::type_index>> _message_map;
public:
MessageableObject()
{
}
template<typename F>
void addMessage(const char* name, F func)
{
auto type = std::type_index(typeid(func));
_message_map.insert(std::make_pair(name, std::make_pair((_message_ptr)func, type)));
}
template<typename R, typename... Args>
R sendMessage(const char* name, Args&&... args)
{
auto iter = _message_map.find(name);
assert(iter != _message_map.end());
auto type = iter->second;
auto func = reinterpret_cast<R(MessageableObject::*)(Args ...)>(type.first);
assert(type.second == std::type_index(typeid(func)));
return func(std::forward<Args>(args)...);
}
void foo()
{
std::cout << __FUNCTION__ << std::endl;
}
int bar(int i, int j)
{
std::cout << __FUNCTION__ << ' ' << i + j << std::endl;
return i + j;
}
};
int main()
{
MessageableObject obj;
obj.addMessage("foo", &MessageableObject::foo);
obj.addMessage("bar", &MessageableObject::bar);
obj.sendMessage<void>("foo");
int baz = obj.sendMessage<int>("bar", 1, 2);
return 0;
}
Currently, this code generates the following error twice:
C2064: term does not evaluate to a function taking n arguments
The first time with n being 0 for when I attempt to call foo, and n being 2 for when I attempt to call bar. Why are these errors occuring? And can I even implement this using the current syntax?
For reference, the version of this implementation that works on non-member functions can be found here: https://stackoverflow.com/a/33837343/962805
Any and all help is greatly appreciated. I'm not very knowledgeable on type erasure and member function binding. The intent for this is to create dynamic messaging a-la unity engine's GameObject.sendMessage function.
Update: As according to skypjack's answer below, the above solution will break if the message call contains a variable. It can be fixed by changing Args&&... in sendMessage to Args..., however this poses a new issue: if a message is added to the map that contains a reference parameter (such as int bar(int&, int)), it will not be able to be called implicitly. Calling sendMessage<int, int&, int>("bar", x, 2) will function as intended.
If you include <cassert> at the top of the file and use this:
return (this->*func)(std::forward<Args>(args)...);
Instead of this:
return func(std::forward<Args>(args)...);
It compiles.
I cannot say that it works for it looks to me you are fortunately avoiding an UB and it apparently works (that is a perfectly valid UB) would be more appropriate.
The problem is that bar has type:
int(MessageableObject::*)(int i, int j);
And you cast it cast to:
void(MessageableObject::*)(void);
Then you cast back it to it's correct type for you are invoking it as:
obj.sendMessage<int>("bar", 1, 2);
If you did instead this:
int x = 1;
obj.sendMessage<int>("bar", x, 2);
You would have performed a cast to:
int (MessageableObject::*)(int &i, int j);
Something similar would happen with a wrong return type. All these are UB. Therefore too weak a solution to use it in a production environment from my point of view.
I want to call all types of functions from a single table.
(Consider returns types are all void)
To illustrate what I am talking about, here is some code that obviously does not work.
#include <iostream>
#include <map>
#include <functional>
void foo(int x){std::cout<<x;}
void bar(){std::cout<<"bar";}
std::map<std::string, std::function<void()>> map =
{
{"foo", foo},
{"bar", bar}
};
int main()
{
map["foo"](2);
map["bar"]();
}
I am not opposed to a C style solution.
You could declare your pointer an old style C function pointer to
a variadic function like:
foo(...);
bar(...);
std::map<void(*)(...)> map =
{
{"foo", foo},
{"bar", bar}
};
but then foo and bar have to follow the variadic calling convention with va_args, va_start
etc and you may only pull C PODs from the list. Don't know if its worth the hassle. The calling method still somehow has to know which number of args to pass.
Looks a bit as if you may rethink your design.
If for example this is supposed to be a command table for a kind of CLI it might be better to pass an std::vector<std::string> to each potential command and make it figure out if the vector has the correct size() for its purpose.
If you totally forsake the type system, you can use boost::any as long as you get all the types exactly right everywhere. Right now only works with explicitly making everything a std::function but I'm sure there's a workaround for that too (update added an overload for free functions):
class Functions
{
public:
template <typename... T>
void add_function(const std::string& name, void (*f)(T...))
{
fs[name] = std::function<void(T...)>{f};
}
template <typename... T>
void add_function(const std::string& name, std::function<void(T...)> f)
{
fs[name] = f;
}
template <typename... T>
void call(const std::string& name, T... args)
{
auto it = fs.find(name);
if (it != fs.end()) {
auto f = boost::any_cast<std::function<void(T...)>>(&it->second);
if (f) {
(*f)(args...);
}
else {
std::cout << "invalid args for " << name << std::endl;
}
}
else {
std::cout << "not found: " << name << std::endl;
}
}
private:
std::map<std::string, boost::any> fs;
};
void baz() {
std::cout << "baz" << std::endl;
}
int main() {
std::function<void()> foo = []{ std::cout << "foo" << std::endl; };
std::function<void(int)> bar = [](int i){ std::cout << "bar(" << i << ")" << std::endl;
};
Functions f;
f.add_function("foo", foo );
f.add_function("bar", bar);
f.add_function("baz", baz);
f.call("foo");
f.call("bar", 42);
f.call("baz");
}
Functional, yes. Good idea? Note also that f.call("bar", 42u) will fail because you have to get every type exactly right.
I changed a bit your approach, and be aware it's just an example, I'm pretty sure it won't compile like this, but it will give you an idea of what I had in mind.
You can register your functions in an additional struct, and then call the appropriate one, forwarding the parameters.
struct Funcs
{
std::function<void(int)> _f1;
std::function<void()> _f2;
template<typename args...>
void call(std::string&& f_name, args...)
{
if(f_name == "foo")
_f1(std::forward(args)...)
if(f_name == "bar")
_f2(std::forward(args)...)
}
}
int main()
{
Funcs f;
f.call("foo", 2);
}
If you really want to store any function, and can always figure out how to call it correctly, you can expand on Oncaphillis' approach and just go ahead and cast the function pointers:
void foo(int);
float bar(double, struct baz);
std::map<void(*)()> map = {
{"foo", (void(*)())foo},
{"bar", (void(*)())bar}
};
Then you can cast them back when you use them:
//code to make sure that map["foo"] is of type `void(*)(int)`
(*(void(*)(int))map["foo"])(42);
//code to make sure that map["bar"] is of type `float(*)(double, struct baz)`
float result = (*(float(*)(double, struct baz))map["foo"])(3.14159, (struct baz){ /*whatever*/});
As you see, it is no problem to call any type of function that way, without restricting to variadic ones. However, this approach is very error prone as you completely do away with the safety provided by the type system, and your casts must be 100% correct. Weird stuff may happen if you don't. That's the same problem as with using boost::any.
Basically, I am implementing a container class. I need to create a method which sorts the data according to the comparator function/functor which must be passed with the sort request. Since declaration and definition of the method are in different files(.h and .cpp) using templates becomes a problem (and I don't have much experience using them). In other words, I want to make a method:
void sort(function/functor f);
and I don't know how to define the function. So, is there any solution to this problem?
If you know the signature of the function/functor to be passed[*], you can use std::function. Or boost::function if you don't have C++11. So for a comparator it would be:
void sort(std::function<bool(const Element&, const Element&)> f);
where Element is the type of the elements of the container.
Failing that you could define a class with a virtual compare function, and allow callers to derive from it with their own class. It's more work for callers, but that's exactly what std::function provides: a way for callers to not have to do that.
Two warnings:
make sure there's really a good reason for the implementation of your container not to be in the header file. All of the standard containers are implemented in header files, and that mostly works OK.
make sure there's really a good reason for you to implement a sort function. Standard containers only have sort functions where std::sort doesn't work: std::list and std::forward_list.
[*] Actually std::function doesn't require the exact same signature. You just say the types you want to call it with and the type you want to convert the return value to. So if you call it with two ints and the caller provides a function that takes two longs, then that's fine. The arguments are converted just like the function call would without any std::function.
This is generally done with templates. Like this:
#include <iostream> // For example output only.
template <typename F>
void sort(F&& pred) {
pred(123);
}
void normal_func(int v) {
std::cout << "normal_func(" << v << ")\n";
}
struct my_pred {
void operator()(int v) const {
std::cout << "my_pred(" << v << ")\n";
}
};
int main() {
sort([](int v) { std::cout << "Called lambda func with " << v << '\n'; });
sort(normal_func);
sort(my_pred());
}
If, however, templates cannot be used, then your best bet would be to use polymorphic function wrapper like std::function (or boost::function, or you can write your own simple version).
Alternatively, you can use a hardcore C-style regular function along with a void pointer where user can save their context. For example, like qsort(). Though I'd try not to go there if possible.
Here is an example using std::function:
#include <iostream> // For example output only.
#include <functional> // For std::function.
void sort(const std::function<void(int)>& pred) {
pred(123);
}
void normal_func(int v) {
std::cout << "normal_func(" << v << ")\n";
}
struct my_pred {
void operator()(int v) const {
std::cout << "my_pred(" << v << ")\n";
}
};
int main() {
sort([](int v) { std::cout << "Called lambda func with " << v << '\n'; });
sort(normal_func);
sort(my_pred());
}
Hope it helps.
You can use std::function as suggested in Steve Jessop's answer but in this case I think you should consider making your sort function a template function as in Vlad's answer. A sort function has to call the comparator many times and there will be noticeable overhead to using std::function in this situation.
The easiest solution is to use a template:
class C
{
template<typename T>
void sort(T func)
{
func(12,45); // Will compile as long as your function/functor
} // Can take two integers as parameters.
}; // NOTE: or integers can be converted into your parameters.
If you want to specify using old C notation.
typedef void (*FUNC_TYPE)(int, int); // declares a function pointer type.
// returns void takes two integers.
class C
{
void sort(FUNC_TYPE func)
{
func(12,45); // Compiles only if the function
} // matches the exact type.
};
The C++11 way
class C
{
void sort(std::function<void(int,int)> func)
{
func(12,45); // Will match any func/functor that
// will return a void and takes two
} // integers.
};
I know this question might be a little weird but the creators of C++ made it so that whenever we create a function in C++ we can specify what we want our parameters to be for example we can create a function like this:
void function(int test);
As well as we can create a function like this:
void function(std::string test);
How do I re-create that effect? I'm in the midst of creating a delegate class that works somewhat like CA# delegates but I'm having a problem when it comes to the parameters. I don't know what type of variable they'll want to store in the delegate so I have to implement something that they can specify which variable types they'll be using. Something like this:
Delegate myDelegate(std::string, int, float);
Is it possible to do that? I've looked into variadic functions but you have to know which type to cast it too. I know I could have indicators like "%d and %s" just like the printf function but is there a way to implement it so that it accepts the object names rather than a indicator? I hope this is simple to understand.
You can use variadic argument lists. Here is a quick example:
#include <algorithm>
#include <iostream>
#include <vector>
#include <functional>
template <typename... T>
class Delegate {
std::vector<std::function<void(T...)>> d_delegates;
public:
template <typename F>
void add(F&& f) { this->d_delegates.push_back(std::forward<F>(f)); }
template <typename... S>
void operator()(S... args) const {
std::for_each(this->d_delegates.begin(), this->d_delegates.end(),
[&](std::function<void(T...)> const& f){ f(args...); });
}
};
void f1(int i) { std::cout << "f1(" << i << ")\n"; }
void f2(int i, double d) { std::cout << "f2(" << i << ", " << d << ")\n"; }
int main() {
Delegate<int> d1;
d1.add(f1);
d1(17);
Delegate<int, double> d2;
d2.add(f2);
d2(42, 3.14);
}
A simple solution would just be function overloading. Also, if future code maintenance is required, it would provide the most clarity (at least that is my hunch). Anyway, this would produce exactly the behavior you are describing.
consider this simple and pointless code.
#include <iostream>
struct A {
template<int N>
void test() {
std::cout << N << std::endl;
}
};
int main() {
A a;
a.test<1>();
}
It is a very simple example of a function template. What if however, I wanted to replace A::test with an overloaded operator() to make it a functor?
#include <iostream>
struct A {
template<int N>
void operator()() {
std::cout << N << std::endl;
}
};
int main() {
A a;
a<1>(); // <-- error, how do I do this?
}
Certainly if the operator() took parameters which were dependent on the template, the compiler could possibly deduce the template. But I just can't figure out the proper syntax to specify template parameters with a parameterless functor.
Is there a proper way to do this?
Obviously, this code would work since it bypasses the functor syntax:
a.operator()<1>();
but that kinda defeats the purpose of it being a functor :-P.
You can only call
a.operator()<1>();
but that would not be using a functor. Functors need a non template operator(), as they must be able to be called as varname() and that won't work with your code.
To make it a real functor change your code a template class (functors are classes):
#include <iostream>
template<int N>
struct A {
void operator()() {
std::cout << N << std::endl;
}
};
int main() {
A<1> a;
a();
}
There's not another "direct" way I know other than the:
a.operator()<1>();
syntax. If you're open to changing the code, moving the template parameter to the class would work, or using a (boost|tr1)::bind to make a (boost|tr1)::function object.
You are trying to pass a template parameter to an instance of an object, which as far as I know is not allowed. You can only pass templates parameters to template functions or template objects.
a.test<1>(); and a.operator()<1>(); work because they are serving as template functions.
Use boost::bind (check out boost libraries) to fix it though.
struct A {
void operator()(int n) {
std::cout << n << std::endl;
}
};
int main(int argc, char* argv[]) {
A a;
boost::function<void()> f = boost::bind<void>(a, 1);
f(); // prints 1
return 0;
}
And you don't even have to mess with templates!
You're stuck. Have you considered something like
struct A {
template<int N>
struct B
{
void operator()()
{ std::cout << N << std::endl; }
};
template<int N>
B<N> functor() {return B<N>();}
};
int main()
{
A a;
a.functor<1>()();
}
Nope, there's no way around it. Like you said, you have to either call the operator explicitly (which defeats the purpose), or the template arguments must be able to be deduced by the compiler.