I need to design a map, which save all function i may use in the futures.
all the functions will have double as its return value.
and all function share a common parameters const std::vector<float>&
so i define the map as:
typedef std::function<double(const std::vector<float>&)> func;
std::unordered_map<std::string, func> f_map;
for example. if i have a function looks like:
double func1(const std::vector<float>& v) {
return 0.; // just a demo
}
i can put it into map like this:
f_map.emplace("2015", static_cast<double(*)(const std::vector<float>&)>(func1));
it's ok since i tested it.
but the problem is:
i also have some function like this:
double func2(int a, const std::vector<float>& v) {
return 0.; // just for demo
}
how can i input this kind of function in my map?
std::bind doesnt work if i do like this:
f_map.emplace("2000", static_cast<double(*)(const std::vector<float>&)>(std::bind(func2, 1)));
can you help on this?
and can you give me your advice on how to save function into map better, thanks very much
What you're asking is essentially the same as:
How can I store both int and float in a map and use them equally?
Functions with different parameters are simply different. A map can only hold a single type. Suppose you get function "2019", how will you or the compiler ever know what kind of function it is?
There are a couple of ways to solve this problem. The essence is to have them be the same type. With std::bind you're on the right track. The correct way to use bind with parameters is to use the std::placeholders.
Say we have this function, double DoThing(int num, std::vector<float>& vec), and wish to fill in the first parameter, but leave the second one open for later. We can do:
mymap.emplace("2000", std::bind(&DoThing, 123, std::placeholders::_1));
You are free to shift the placeholder around however you like and add other ones too.
If you store the object bind returns and later get it back you can call it like so:
mymap["2000"](vec); //will call DoThing(123, vec)
Also. std::bind returns an object that holds both the function pointer to DoThing and any value you prefilled as well. Casting this to a function pointer like you did is not possible. That object is not a problem here since std::function, the map's contained type, has functionality to also store and, later, be able to call this object correctly.
Simillarly you can use lambda's to achieve the same effect as bind:
mymap.emplace("2000", [](std::vector<float>& vec){ return DoThing(123, vec); });
Other possibilities include unions/variants or other possibly tricky stuff. Though these methods will only make your code more complex if you don't know how to use them, so I don't recommend these.
Avoiding type casts is better and more safe. The first emplace [1] is valid without static_cast.
You should inform std::bind where to place the unbound argument with help of placeholders [2]. _1 of the namespace std::placeholders sets the unbound argument v to be the first argument of the resulting functional object.
If you use not capturing lamba expression, you can store pointers to functions. Pointers take less bytes than std::function objects. See [3].
#include <functional>
#include <string>
#include <unordered_map>
double func1(const std::vector<float>&) {
return 0.; // just a demo
}
double func2(int, const std::vector<float>&) {
return 0.; // just for demo
}
int main() {
using namespace std::placeholders;
typedef std::function<double(const std::vector<float>&)> func;
std::unordered_map<std::string, func> f_map;
f_map.emplace("2015", func1); // [1]
f_map.emplace("2000", std::bind(func2, 1, _1)); // [2]
// [3]
typedef double(*pfunc)(const std::vector<float>&);
std::unordered_map<std::string, pfunc> f_map2;
f_map2.emplace("2015", func1);
f_map2.emplace("2000", [](const std::vector<float>&v) { return func2(1, v); });
}
Related
I am working on a problem that requires me to return different return-types based on my function parameter values that I provide.
I want to do something like this --
In the code below, doSomething() is an already existing function (used by a lot of clients) which takes mode as a function parameter, and returns std::list<ReturnType> already.
Based on the mode value, I had to create another sub-functionality which returns a shared_future<std::list<ReturnType>>.
How can I change this code so that it can return one of the two return types based on the mode value?
Note: ReturnType is a template typename which we are using for the entire class.
Code:
std::shared_future<std::list<ReturnType> > futureValue() {
return functionReturningSharedFuture();
}
std::list<ReturnType> listValue() {
return functionReturningList();
}
std::list<ReturnType> doSomething(int mode) {
if(mode == 1){
// new functionality that I added
return futureValue(); // This (obviously) errors out as of now
}
else{
// already there previously
return listValue();
}
}
int main() {
doSomething(1);
return 0;
}
How can I change this code so that it can return one of the two return types based on the mode value?
Constraints and Issues:
This issue could've been easily solved by function overloading if we provide an extra function parameter (like a true value), but that extra argument is not useful, since we are already using mode. Also, it isn't considered a good design to add variables which have almost no use.
One of the major constraints is that there are clients who are already using this doSomething() expect a std::list<ReturnType>, and so I cannot return boost::any or std::variant or anything similar.
I tried using std::enable_if, but it wasn't working out since we are getting the mode value at runtime.
We can't use template metaprogramming since that would change the way our function is being called on the client-side. Something that we can't afford to do.
Thank you.
This cannot be done.
You can only have one function with a given signature. If you have calling code that already expects this to return a std::list<ReturnType>, that's it; you're done.
If you could guarantee that all existing calling code looks like
auto l = obj.doSomething(1);
then you could potentially change the return type to something which would look like a std::list to any calling code. But if there's any calling code that looks like
std::list<ReturnType> l = obj.doSomething(1);
then that's off the table.
You probably need to rethink your design here.
From the example main, I see doSomething(1);, so maybe at the call site the value of the parameter mode is always known at compile-time. In this case, one option is that you make doSomething a template<int mode> function. I'm thinking about something like this:
#include <iostream>
#include <list>
#include <vector>
// assuming you cannot change this (actually you have changed it in you example, ...)
std::list<int> doSomething(int mode) {
std::cout << "already existing function\n";
return std::list<int>{1,2,3};
}
// then you can put this too
template<int N>
auto doSomething();
template<>
auto doSomething<10>() {
std::cout << "new function\n";
return std::vector<int>{1,2,3};
}
int main() {
auto x = doSomething(3);
auto y = doSomething<10>();
}
Probably another option would be to use a if constexpr intead of if and an auto/decltype(auto) return type in doSomething, but I haven't tried it.
I have a function declared as int __stdcall MyFunction(int param, int param); and I need to get a type of the pointer to the function in a macro or a template when the name is passed as a parameter.
Is this possible in C++ or do I have to rewrite the function signature myself?
You can make a type alias for a function pointer (to which it decays, or which is returned by the address-of operator) the following way:
#include <iostream>
int MyFunction(int param, int param1)
{
std::cout << param << " " << param1 << std::endl;
return 0;
}
using Myfunction_ptr_t = std::decay<decltype(MyFunction)>::type;
// or using Myfunction_ptr_t = decltype(&MyFunction);
// or using Myfunction_ptr_t = decltype(MyFunction) *;
int main()
{
Myfunction_ptr_t Myfunction_ptr = MyFunction;
Myfunction_ptr(1, 2);
}
This example should rather use the auto specifier (since C++ 11):
auto Myfunction_ptr = MyFunction;
but that won't help in non-deducible context.
Function pointer behaves like every other pointer. It is a memory address which points to some entity (function code in this case). You can save these pointers somewhere and then fetch them in any convenient for your situation way.
For example you can create static map of std::string vs fun. pointer pairs:
static std::map<std::string, PTR_TYPE> funMap;
After that save pointers to this map and retreive them when needed.
If you don't have pointer yet, probably you speak about exported functions from libraries. In this case look at ldd for *nix-based or somethig simialar for other platform. You will need to search for runtime linker information and find fnction by it's name.
Actually I don't understand why you say you can't link against those functions. Do it in standard way: include header file with such declarations. Use declaration. Linker will do the work for you. Just provide it a path to library with those functions. It will link dynamically to required functions. That's all what you should do. If you don't have such library you need to search for function at runtime manualy with the help of (again) linker at runtime.
You could define a typedef like below:
typedef int (__stdcall *MYFUN)(int, int);
Test case:
int main() {
MYFUN f = MyFunction;
f(2, 3);
}
Alternatively, you could use a std::function object as bellow:
std::function<decltype(MyFunction)> myfun;
Test case:
std::function<decltype(MyFunction)> myfun = MyFunction;
myfun(4, 5);
Live Demo
Got it. decltype(FunctionName)* pointer; will do the job.
You could use decltype or auto, like the following
decltype(&FunctionName) pointer = &FunctionName;
or
auto pointer = &FunctionName;
I avoid manually translating function pointers to types myself in C++11 and C++14 :)
Say that you define a callback function as such:
typedef std::function<void(float)> Callback;
And you have a function as such:
void ImAFunction(float a)
{
//Do something with a
}
Is there a way to be able to store a function without an argument then pass one to it at a later time?
Such as this:
//Define the Callback storage
Callback storage;
storage = std::bind(ImAFunction, this);
//Do some things
storage(5);
This wont work which I explain with some of my real code below.
I can get close to what I wan't if I bind the value in with the std::bind function. Such as:
//Change
//storage = std::bind(ImAFunction, this);
storage = std::bind(ImAFunction, this, 5.0); //5.0 is a float passed
This works but when I go to pass a value through the function the outcome is whatever I set it to before:
storage(100); //Output is still 5
I am basing the fact that I think this is possible on this article.
http://www.cprogramming.com/tutorial/function-pointers.html
It doesn't use the function or bind functions but it does pass pointer arguments and performs exactly what I need. The reason I don't just skip the bind function is because I am trying to store the function in a class (private) and I can't store it if it's a template because it's created with the class.
The error produced above comes from this code:
struct BindInfo {
Callback keyCallback;
int bindType;
bool isDown;
bool held;
std::string name;
};
template <class T1>
void bindEvent(int bindType, T1* keydownObj, void(T1::*keydownF)(float), std::string name)
{
BindInfo newKeyInfo = { std::bind(keydownF, keydownObj), bindType, false, false, name };
inputBindings.insert(std::pair<int, BindInfo>(BIND_NULL, newKeyInfo));
};
The error is:
No viable conversion from '__bind<void(Main::*&)(float), Main *&>' to 'Callback' (aka 'function<void (float)>'
Is this possible? Thanks in advance.
You can include a placeholder for an unbound argument:
std::bind(&Main::ImAFunction, this, std::placeholders::_1);
If you find that a bit of a mouthful, a lambda might be more readable:
[this](float a){ImAFunction(a);}
It sounds like what you're looking for is a function pointer. While I don't have a lot of experience using them in C++ I have used them in C so: Yes, it is possible. Perhaps something like this:
void (*IAmAFunctionPointer)(float) = &IAmAFunction;
The best way to think about that line is, that IAmAFunctionPointer is a pointer (hence the *), it returns a void, and takes a float. Then later:
float a = 5;
IAmAFunctionPointer(a);
You could even design it so that the callback function is passed into the method (I assume this is what you're looking for).
void DoStuffThenCallback(float a, void (*callback)(float))
{
//DoStuff
callback(a);
}
further reading: http://www.cprogramming.com/tutorial/function-pointers.html
I can't seem to find any relevant information on the following sort of thing.
Say that you have a program with numerous methods (for example, a custom set of tests).
How could you loop through them based on something like the following pseudo-code
for(int i= 0; i < 10 ; i ++)
{
function(i)();
}
so that it will go through this loop and therefore launch methods function0, function1, function2, function3, function4, function5, function6, function7, functuin8, function9.
If there are ways to also do this in C# or Java, then information for them also would be appreciated.
In C++, the only way I can think of is to use of an array of function pointers. See here.
For Java, which supports Reflection, see this. And for C#, which also supports Reflection, this.
The language feature you would need for this is called "Reflection", which is a feature C++ does not have. You will need to explicitly name the functions you want to call.
Well, if you have an array of function pointers, you can do something like this:
void (*myStuff[256])(void);
And then when you want to call each function just dereference each of them as you iterate.
Keep in mind that every function in your array must have the same parameter signature and return type.
Here's a solution using Boost.Function and Boost.Bind in which the loop doesn't need to worry about the parameter signatures of the functions you are calling (I haven't tested it in a compiler, but I have very similar code in a project which I know works):
#include <vector>
#include <boost/function.hpp>
#include <boost/bind.hpp>
using std::vector;
using boost::function;
using boost::bind;
void foo (int a);
void bar (double a);
void baz (int a, double b);
int main()
{
// Transform the functions so that they all have the same signature,
// (with pre-determined arguments), and add them to a vector:
vector<function<void()>> myFunctions;
myFunctions.push_back(bind(&foo, 1));
myFunctions.push_back(bind(&bar, 2.0));
myFunctions.push_back(bind(&baz, 1, 2.0));
// Call the functions in a loop:
vector<function<void()>>::iterator it = myFunctions.begin();
while (it != myFunctions.end())
{
(*it)();
it++;
}
return 0;
}
Note that you can do the loop much easier if your compiler supports C++11:
// Call the functions in a loop:
for (const auto& f : myFunctions)
{
f();
}
Boost.Bind also supports passing in certain parameters dynamically instead of binding them to pre-determined values. See the documentation for more details. You could also trivially alter the above code to support return values (if they are of the same type), by replacing void with the return type, and altering the loop to do something with the returned value.
Is it possible to store pointers to various heterogenous functions like:
In the header:
int functionA (int param1);
void functionB (void);
Basically this would the part I don't know how to write:
typedef ??boost::function<void(void)>?? functionPointer;
And afterwards:
map<char*,functionPointer> _myMap;
In the .cpp
void CreateFunctionMap()
{
_myMap["functionA"] = &functionA;
_myMap["functionB"] = &functionB;
...
}
And then reuse it like:
void execute(int argc, char* argv[])
{
if(argc>1){
int param = atoi(argv[1]);
int answer;
functionPointer mfp;
mfp = map[argv[0]];
answer = *mfp(param);
}
else{
*map[argv[0]];
}
}
etc.
Thanks
--EDIT--
Just to give more info:
The reason for this question is that I am implementing a drop-down "quake-style" console for an already existing application. This way I can provide runtime command line user input to access various already coded functions of various types i.e.:
/exec <functionName> <param1> <param2> ...
If you want to have "pointer to something, but I'm not going to define what, and it could be a variety of things anyway" you can use void *.
But you really shouldn't.
void * is purely a pointer. In order to do anything with it, you have to cast it to a more meaningful pointer, but at that point, you've lost all type safety. What's to stop someone from using the wrong function signature? Or using a pointer to a struct?
EDIT
To give you a more useful answer, there's no need to put this all into a single map. It's ok to use multiple maps. I.e.
typedef boost::function<void(void)> voidFunctionPointer;
typedef boost::function<int(int)> intFunctionPointer;
map<std::string, voidFunctionPointer> _myVoidMap;
map<std::string, intFunctionPointer > _myIntMap;
void CreateFunctionMap()
{
_myVoidMap["functionA"] = &functionA;
_myIntMap["functionB"] = &functionB;
...
}
void execute(int argc, char* argv[])
{
if(argc>1){
int param = atoi(argv[1]);
int answer;
// todo: check that argv[0] is actually in the map
intFunctionPointer mfp = _myIntMap[argv[0]];
answer = mfp(param);
}
else{
// todo: check that argv[0] is actually in the map
voidFunctionPointer mfp = _myVoidMap[argv[0]];
mfp();
}
}
You can use
boost::variant<
boost::function<void(void)>,
boost::function<void(int)> >
Why not just add functions of type int (*func)(int argc, char* argv[])? You could easily remove first arg from execute's params and call the relevant one.
Can you not use the command pattern to encapsulate the function calls. So you can store the functions in functors and call them after wards. For functor implementation you can have a look at Modern C++ Design by Andrei Alexandrescu.
Each of your functions has a different type, so you need some kind of type erasure. You could use the most generic of them: Boost.Any. You can have a map of boost::any, but you need to know the type of the function in order to get it back and call it.
Alternatively, if you know your arguments ahead of time you can bind them with the function call and have all functions in the map be nullary functions: function< void() >. Even if you don't, you may be able to get away with it by binding the argument to references, and then at call time fill the referred variables with the appropiate arguments.