c++ build a name to function table, functions have different signature
I want to know, if it is possible to build a name to function table in c++, something like map<string, function handle>. But
those functions have different signatures. I can assume they have same return type as
void.
I was thinking define something like,
struct ftable
{
std::string name;
void (void* pfun)(); // this is only for one function signature
};
But how to make it work for different types of function?
I asked a related question here. In that question, I try to store functions into some container, but I realize that I can not store function with placeholder (see following code). Is this possible with c++? Thanks!
template <typename F, typename ... Args>
std::function<void()> MapFun (F const & f, Args const & ... args)
{ return [=]{ f(args...); }; }
void userFun1 (int i1, int i2)
{ std::cout << "uf1, " << i1 << ", " << i2 << std::endl; }
int main ()
{
auto l1 = MapFun(userFun1, 1, 2);
std::unordered_map<std::string, std::function<void()>> func_map;
func_map["userFun1"] = std::bind(l1); // this is okay;
//func_map["userFun1"] = std::bind(userFun1, std::placeholders::_1, std::placeholders::_2); // this is wrong;
//auto lll1 = MapFun(userFun1, std::placeholders::_1,std::placeholders::_2); // also wrong.
}
UPDATE: What I want is like plugin development. I have a server and a client. I can write my function on client, and build it as a shared library, then send that shared library to server as well as a signal telling server to load it. I hope server program can load function with different signatures from shared library without restart or rebuild. Is this possible, or I have to fix the signature and restrict all shared functions with that?
c++ function c++11 c++17
|
show 9 more comments
I want to know, if it is possible to build a name to function table in c++, something like map<string, function handle>. But
those functions have different signatures. I can assume they have same return type as
void.
I was thinking define something like,
struct ftable
{
std::string name;
void (void* pfun)(); // this is only for one function signature
};
But how to make it work for different types of function?
I asked a related question here. In that question, I try to store functions into some container, but I realize that I can not store function with placeholder (see following code). Is this possible with c++? Thanks!
template <typename F, typename ... Args>
std::function<void()> MapFun (F const & f, Args const & ... args)
{ return [=]{ f(args...); }; }
void userFun1 (int i1, int i2)
{ std::cout << "uf1, " << i1 << ", " << i2 << std::endl; }
int main ()
{
auto l1 = MapFun(userFun1, 1, 2);
std::unordered_map<std::string, std::function<void()>> func_map;
func_map["userFun1"] = std::bind(l1); // this is okay;
//func_map["userFun1"] = std::bind(userFun1, std::placeholders::_1, std::placeholders::_2); // this is wrong;
//auto lll1 = MapFun(userFun1, std::placeholders::_1,std::placeholders::_2); // also wrong.
}
UPDATE: What I want is like plugin development. I have a server and a client. I can write my function on client, and build it as a shared library, then send that shared library to server as well as a signal telling server to load it. I hope server program can load function with different signatures from shared library without restart or rebuild. Is this possible, or I have to fix the signature and restrict all shared functions with that?
c++ function c++11 c++17
5
Why do you think you need this? Sounds like and XY problem to me. What is the underlying problem you are trying to solve?
– super
Nov 15 '18 at 5:11
7
After you retrieve a function from the map, how will you know what its signature is?
– Raymond Chen
Nov 15 '18 at 5:13
@RaymondChen I think you are right. C++ is a language needs to know type at compilation.
– J.Yang
Nov 15 '18 at 14:30
I have updated my question, @super, thanks for your comment
– J.Yang
Nov 15 '18 at 14:31
If you know the signature at compile time (e.g. "The item namedbobis always avoid(*)(int,int)") then you can cast a plain function pointer tovoid(*)()for storage, then cast it tovoid(*)(int,int)after retrieving. Function pointers of different signature can be interconverted without loss of fidelity, but you have to cast back to the original type before using them to call the function. If you cast to the wrong signature and then try to call the function, the result is undefined (i.e., "bad").
– Raymond Chen
Nov 15 '18 at 15:37
|
show 9 more comments
I want to know, if it is possible to build a name to function table in c++, something like map<string, function handle>. But
those functions have different signatures. I can assume they have same return type as
void.
I was thinking define something like,
struct ftable
{
std::string name;
void (void* pfun)(); // this is only for one function signature
};
But how to make it work for different types of function?
I asked a related question here. In that question, I try to store functions into some container, but I realize that I can not store function with placeholder (see following code). Is this possible with c++? Thanks!
template <typename F, typename ... Args>
std::function<void()> MapFun (F const & f, Args const & ... args)
{ return [=]{ f(args...); }; }
void userFun1 (int i1, int i2)
{ std::cout << "uf1, " << i1 << ", " << i2 << std::endl; }
int main ()
{
auto l1 = MapFun(userFun1, 1, 2);
std::unordered_map<std::string, std::function<void()>> func_map;
func_map["userFun1"] = std::bind(l1); // this is okay;
//func_map["userFun1"] = std::bind(userFun1, std::placeholders::_1, std::placeholders::_2); // this is wrong;
//auto lll1 = MapFun(userFun1, std::placeholders::_1,std::placeholders::_2); // also wrong.
}
UPDATE: What I want is like plugin development. I have a server and a client. I can write my function on client, and build it as a shared library, then send that shared library to server as well as a signal telling server to load it. I hope server program can load function with different signatures from shared library without restart or rebuild. Is this possible, or I have to fix the signature and restrict all shared functions with that?
c++ function c++11 c++17
I want to know, if it is possible to build a name to function table in c++, something like map<string, function handle>. But
those functions have different signatures. I can assume they have same return type as
void.
I was thinking define something like,
struct ftable
{
std::string name;
void (void* pfun)(); // this is only for one function signature
};
But how to make it work for different types of function?
I asked a related question here. In that question, I try to store functions into some container, but I realize that I can not store function with placeholder (see following code). Is this possible with c++? Thanks!
template <typename F, typename ... Args>
std::function<void()> MapFun (F const & f, Args const & ... args)
{ return [=]{ f(args...); }; }
void userFun1 (int i1, int i2)
{ std::cout << "uf1, " << i1 << ", " << i2 << std::endl; }
int main ()
{
auto l1 = MapFun(userFun1, 1, 2);
std::unordered_map<std::string, std::function<void()>> func_map;
func_map["userFun1"] = std::bind(l1); // this is okay;
//func_map["userFun1"] = std::bind(userFun1, std::placeholders::_1, std::placeholders::_2); // this is wrong;
//auto lll1 = MapFun(userFun1, std::placeholders::_1,std::placeholders::_2); // also wrong.
}
UPDATE: What I want is like plugin development. I have a server and a client. I can write my function on client, and build it as a shared library, then send that shared library to server as well as a signal telling server to load it. I hope server program can load function with different signatures from shared library without restart or rebuild. Is this possible, or I have to fix the signature and restrict all shared functions with that?
c++ function c++11 c++17
c++ function c++11 c++17
edited Nov 15 '18 at 14:28
J.Yang
asked Nov 15 '18 at 5:04
J.YangJ.Yang
246
246
5
Why do you think you need this? Sounds like and XY problem to me. What is the underlying problem you are trying to solve?
– super
Nov 15 '18 at 5:11
7
After you retrieve a function from the map, how will you know what its signature is?
– Raymond Chen
Nov 15 '18 at 5:13
@RaymondChen I think you are right. C++ is a language needs to know type at compilation.
– J.Yang
Nov 15 '18 at 14:30
I have updated my question, @super, thanks for your comment
– J.Yang
Nov 15 '18 at 14:31
If you know the signature at compile time (e.g. "The item namedbobis always avoid(*)(int,int)") then you can cast a plain function pointer tovoid(*)()for storage, then cast it tovoid(*)(int,int)after retrieving. Function pointers of different signature can be interconverted without loss of fidelity, but you have to cast back to the original type before using them to call the function. If you cast to the wrong signature and then try to call the function, the result is undefined (i.e., "bad").
– Raymond Chen
Nov 15 '18 at 15:37
|
show 9 more comments
5
Why do you think you need this? Sounds like and XY problem to me. What is the underlying problem you are trying to solve?
– super
Nov 15 '18 at 5:11
7
After you retrieve a function from the map, how will you know what its signature is?
– Raymond Chen
Nov 15 '18 at 5:13
@RaymondChen I think you are right. C++ is a language needs to know type at compilation.
– J.Yang
Nov 15 '18 at 14:30
I have updated my question, @super, thanks for your comment
– J.Yang
Nov 15 '18 at 14:31
If you know the signature at compile time (e.g. "The item namedbobis always avoid(*)(int,int)") then you can cast a plain function pointer tovoid(*)()for storage, then cast it tovoid(*)(int,int)after retrieving. Function pointers of different signature can be interconverted without loss of fidelity, but you have to cast back to the original type before using them to call the function. If you cast to the wrong signature and then try to call the function, the result is undefined (i.e., "bad").
– Raymond Chen
Nov 15 '18 at 15:37
5
5
Why do you think you need this? Sounds like and XY problem to me. What is the underlying problem you are trying to solve?
– super
Nov 15 '18 at 5:11
Why do you think you need this? Sounds like and XY problem to me. What is the underlying problem you are trying to solve?
– super
Nov 15 '18 at 5:11
7
7
After you retrieve a function from the map, how will you know what its signature is?
– Raymond Chen
Nov 15 '18 at 5:13
After you retrieve a function from the map, how will you know what its signature is?
– Raymond Chen
Nov 15 '18 at 5:13
@RaymondChen I think you are right. C++ is a language needs to know type at compilation.
– J.Yang
Nov 15 '18 at 14:30
@RaymondChen I think you are right. C++ is a language needs to know type at compilation.
– J.Yang
Nov 15 '18 at 14:30
I have updated my question, @super, thanks for your comment
– J.Yang
Nov 15 '18 at 14:31
I have updated my question, @super, thanks for your comment
– J.Yang
Nov 15 '18 at 14:31
If you know the signature at compile time (e.g. "The item named
bob is always a void(*)(int,int)") then you can cast a plain function pointer to void(*)() for storage, then cast it to void(*)(int,int) after retrieving. Function pointers of different signature can be interconverted without loss of fidelity, but you have to cast back to the original type before using them to call the function. If you cast to the wrong signature and then try to call the function, the result is undefined (i.e., "bad").– Raymond Chen
Nov 15 '18 at 15:37
If you know the signature at compile time (e.g. "The item named
bob is always a void(*)(int,int)") then you can cast a plain function pointer to void(*)() for storage, then cast it to void(*)(int,int) after retrieving. Function pointers of different signature can be interconverted without loss of fidelity, but you have to cast back to the original type before using them to call the function. If you cast to the wrong signature and then try to call the function, the result is undefined (i.e., "bad").– Raymond Chen
Nov 15 '18 at 15:37
|
show 9 more comments
2 Answers
2
active
oldest
votes
It is possible but at some point you will need to know the return and parameter types.
You can use a type-erasure class to hide the return/parameter types and then store the type-erasure class. A naive implementation like this would suffice,
#include <iostream>
#include <functional>
#include <unordered_map>
class MyLambda {
public:
MyLambda() = default;
virtual ~MyLambda() = default;
};
template <typename T>
class HiddenLambda : public MyLambda {
static_assert(std::integral_constant<T, false>::value, "Template parameter needs to be of function type.");
};
template <typename Ret, typename... Args>
class HiddenLambda<Ret(Args...)> : public MyLambda {
public:
HiddenLambda(std::function<Ret(Args...)> _fun) : fun_(_fun) { }
Ret operator() (Args... args) {return fun_(args...);}
private:
std::function<Ret(Args...)> fun_;
};
int main() {
std::unordered_map<std::string, std::shared_ptr<MyLambda>> my_lambdas;
my_lambdas.insert(std::make_pair("fun1", std::shared_ptr<MyLambda>(
new HiddenLambda<size_t(std::string)>(
(std::string s) { return s.size(); } // <- lambda you want to store
)
)
));
my_lambdas.insert(std::make_pair("fun2", std::shared_ptr<MyLambda>(
new HiddenLambda<int(int)>(
(int x) { return x * 5; } // <- lambda you want to store
)
)
));
auto it = my_lambdas.find("fun1");
/* Get the function we want! */
std::shared_ptr<MyLambda> a_lam = it->second;
/* Need to know the types to actually use it though */
HiddenLambda<size_t(std::string)>& actual_lam = dynamic_cast<HiddenLambda<size_t(std::string)>&>(*a_lam);
std::cout << actual_lam("how long is this string?") << "n";
}
If this is what we really need to do, I suggest looking up various methods for type erasure.
I think the problem you are trying to solve probably has an easier solution. If you could give more details perhaps we could help?
EDIT
More relevant example to your provided code...
/* include above classes and includes */
void myfunc(int x, int y) {
std::cout << "uf1, " << x << ", " << y << std::endl;
}
int main() {
std::unordered_map<std::string, std::shared_ptr<MyLambda>> func_map;
func_map["userFun1"] = std::shared_ptr<MyLambda>(
new HiddenLambda<void(int, int)>( &myfunc ) // <- no args binded, notice the type = void(int,int)
);
func_map["userFun2"] = std::shared_ptr<MyLambda>(
new HiddenLambda<void(int)>( std::bind(myfunc, std::placeholders::_1, 5) ) // <- one args binded, notice the type = void(int)
);
func_map["userFun3"] = std::shared_ptr<MyLambda>(
new HiddenLambda<void()>( std::bind(myfunc, 1, 2)) // <- two args binded, notice the type = void()
);
/* we still need to know the type though,it will be either void(int, int), void(int) or void() */
HiddenLambda<void(int)>& actual_lam = dynamic_cast<HiddenLambda<void(int)>&>(*func_map["userFun2"]);
actual_lam(4);
}
EDIT V2
This is more of a guess then anything. I am not sure if you should do this (well definitely not outside of some interesting experimentation) or if it will even work. Here is a possible way if the amount different arguments for different functions is known and finite. This would require a technique called Library Interposing, which I do not know much about.
Firstly in the main program you define this enum and a factory function. The enum will describe every possible parameter range.
enum Types { kVOID, kINT_INT }; // <- verbosely define all the possible ones you would use
std::pair<Types, std::shared_ptr<MyLambda>> Factory(){
return
{
kVOID, /* <- some sensible default */
std::shared_ptr<MyLambda>(
new HiddenLambda<void()>( {} )
)
};
}
The shared library will have to provide an overriden factory method. Here is where I think you need the interposer to do so.
std::pair<Types, std::shared_ptr<MyLambda>> Factory(){
return
{
kVOID_INT_INT,
std::shared_ptr<MyLambda>(
new HiddenLambda<void(int, int)>( (int x, int y){ std::cout << (x + y);} )
)
};
}
Then the main method would look like:
int main() {
std::unordered_map<std::string, std::pair<Types, std::shared_ptr<MyLambda>>> func_map;
func_map.insert({"fun1", Factory()});
auto it = func_map.find("fun1");
/* always need to be able to deduce they type */
if (it->second.first == kVOID) {
CallHidden(*it->second.second);
}
else if (it->second.first == kINT_INT) {
CallHidden<int, int>(*it->second.second, 3, 4);
} else {
/* other ones you have statically typed */
}
}
Thestatic_assertonly covers view data types (what about floating point types? classes/structs?). Better: Just do not implement the template!
– Aconcagua
Nov 15 '18 at 6:52
Thanks for your answer. But it still need to know the type when get the function handle out from the map. It has the same limitation like usingstd::vector<std::any>. I have updated my question, do you have any other suggestion?
– J.Yang
Nov 15 '18 at 14:40
@J.Yang You always need to know the signature. At some point in your code you will need to give arguments to the function, at that point you need to know the types of all the arguments. I have added an edit that may help.
– Bar Stool
Nov 16 '18 at 7:08
@J.Yang Please let me know if you get it working, I am interested to know what you end up doing. It you are satisfied with this answer, please consider accepting it.
– Bar Stool
Nov 16 '18 at 7:38
@BarStool Thank you for your patient. I need think about your EDIT V2. If this does not work, I think I will fix the signature for the shared function. So it will accept multiple vectors. If I want send a few int inputs, I have to put them all in one vector<int>, and take them out at the beginning of the function.
– J.Yang
Nov 17 '18 at 0:13
add a comment |
If at time of creating object of std::function<void()>, you know function signature then you may be able to do like below.
#include <iostream>
#include <functional>
#include <unordered_map>
void userFun1 (int i1, int i2)
{
std::cout << "uf1, " << i1 << ", " << i2 << std::endl;
}
int main()
{
std::unordered_map<std::string, std::function<void()>> func_map;
func_map["userFun1"] = std::bind(userFun1,1,2);
func_map["userFun1"]();
int i1{2},i2{3};
func_map["userFun1.1"] = std::bind(userFun1,std::ref(i1),std::ref(i2));
func_map["userFun1.1"]();
i1 = 3;
i2 = 4;
func_map["userFun1.1"]();
return 0;
}
Live Code
Thanks for your answer. That std::ref sounds like the tricky. I have updated my question, do you think this can be a workaround?
– J.Yang
Nov 15 '18 at 14:37
@J.Yang For your update,I don't think that may be possible. For any plugin system, there is fixed set of function call OR API which are know to both plugin loader and plugin it self. In your case you can create wrapper of your client code which know what are signature of client function and what are value need to pass to client function and call this wrapper function from your server code. Hope this will help!
– Manthan Tilva
Nov 16 '18 at 5:23
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53312744%2fc-build-a-name-to-function-table-functions-have-different-signature%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
It is possible but at some point you will need to know the return and parameter types.
You can use a type-erasure class to hide the return/parameter types and then store the type-erasure class. A naive implementation like this would suffice,
#include <iostream>
#include <functional>
#include <unordered_map>
class MyLambda {
public:
MyLambda() = default;
virtual ~MyLambda() = default;
};
template <typename T>
class HiddenLambda : public MyLambda {
static_assert(std::integral_constant<T, false>::value, "Template parameter needs to be of function type.");
};
template <typename Ret, typename... Args>
class HiddenLambda<Ret(Args...)> : public MyLambda {
public:
HiddenLambda(std::function<Ret(Args...)> _fun) : fun_(_fun) { }
Ret operator() (Args... args) {return fun_(args...);}
private:
std::function<Ret(Args...)> fun_;
};
int main() {
std::unordered_map<std::string, std::shared_ptr<MyLambda>> my_lambdas;
my_lambdas.insert(std::make_pair("fun1", std::shared_ptr<MyLambda>(
new HiddenLambda<size_t(std::string)>(
(std::string s) { return s.size(); } // <- lambda you want to store
)
)
));
my_lambdas.insert(std::make_pair("fun2", std::shared_ptr<MyLambda>(
new HiddenLambda<int(int)>(
(int x) { return x * 5; } // <- lambda you want to store
)
)
));
auto it = my_lambdas.find("fun1");
/* Get the function we want! */
std::shared_ptr<MyLambda> a_lam = it->second;
/* Need to know the types to actually use it though */
HiddenLambda<size_t(std::string)>& actual_lam = dynamic_cast<HiddenLambda<size_t(std::string)>&>(*a_lam);
std::cout << actual_lam("how long is this string?") << "n";
}
If this is what we really need to do, I suggest looking up various methods for type erasure.
I think the problem you are trying to solve probably has an easier solution. If you could give more details perhaps we could help?
EDIT
More relevant example to your provided code...
/* include above classes and includes */
void myfunc(int x, int y) {
std::cout << "uf1, " << x << ", " << y << std::endl;
}
int main() {
std::unordered_map<std::string, std::shared_ptr<MyLambda>> func_map;
func_map["userFun1"] = std::shared_ptr<MyLambda>(
new HiddenLambda<void(int, int)>( &myfunc ) // <- no args binded, notice the type = void(int,int)
);
func_map["userFun2"] = std::shared_ptr<MyLambda>(
new HiddenLambda<void(int)>( std::bind(myfunc, std::placeholders::_1, 5) ) // <- one args binded, notice the type = void(int)
);
func_map["userFun3"] = std::shared_ptr<MyLambda>(
new HiddenLambda<void()>( std::bind(myfunc, 1, 2)) // <- two args binded, notice the type = void()
);
/* we still need to know the type though,it will be either void(int, int), void(int) or void() */
HiddenLambda<void(int)>& actual_lam = dynamic_cast<HiddenLambda<void(int)>&>(*func_map["userFun2"]);
actual_lam(4);
}
EDIT V2
This is more of a guess then anything. I am not sure if you should do this (well definitely not outside of some interesting experimentation) or if it will even work. Here is a possible way if the amount different arguments for different functions is known and finite. This would require a technique called Library Interposing, which I do not know much about.
Firstly in the main program you define this enum and a factory function. The enum will describe every possible parameter range.
enum Types { kVOID, kINT_INT }; // <- verbosely define all the possible ones you would use
std::pair<Types, std::shared_ptr<MyLambda>> Factory(){
return
{
kVOID, /* <- some sensible default */
std::shared_ptr<MyLambda>(
new HiddenLambda<void()>( {} )
)
};
}
The shared library will have to provide an overriden factory method. Here is where I think you need the interposer to do so.
std::pair<Types, std::shared_ptr<MyLambda>> Factory(){
return
{
kVOID_INT_INT,
std::shared_ptr<MyLambda>(
new HiddenLambda<void(int, int)>( (int x, int y){ std::cout << (x + y);} )
)
};
}
Then the main method would look like:
int main() {
std::unordered_map<std::string, std::pair<Types, std::shared_ptr<MyLambda>>> func_map;
func_map.insert({"fun1", Factory()});
auto it = func_map.find("fun1");
/* always need to be able to deduce they type */
if (it->second.first == kVOID) {
CallHidden(*it->second.second);
}
else if (it->second.first == kINT_INT) {
CallHidden<int, int>(*it->second.second, 3, 4);
} else {
/* other ones you have statically typed */
}
}
Thestatic_assertonly covers view data types (what about floating point types? classes/structs?). Better: Just do not implement the template!
– Aconcagua
Nov 15 '18 at 6:52
Thanks for your answer. But it still need to know the type when get the function handle out from the map. It has the same limitation like usingstd::vector<std::any>. I have updated my question, do you have any other suggestion?
– J.Yang
Nov 15 '18 at 14:40
@J.Yang You always need to know the signature. At some point in your code you will need to give arguments to the function, at that point you need to know the types of all the arguments. I have added an edit that may help.
– Bar Stool
Nov 16 '18 at 7:08
@J.Yang Please let me know if you get it working, I am interested to know what you end up doing. It you are satisfied with this answer, please consider accepting it.
– Bar Stool
Nov 16 '18 at 7:38
@BarStool Thank you for your patient. I need think about your EDIT V2. If this does not work, I think I will fix the signature for the shared function. So it will accept multiple vectors. If I want send a few int inputs, I have to put them all in one vector<int>, and take them out at the beginning of the function.
– J.Yang
Nov 17 '18 at 0:13
add a comment |
It is possible but at some point you will need to know the return and parameter types.
You can use a type-erasure class to hide the return/parameter types and then store the type-erasure class. A naive implementation like this would suffice,
#include <iostream>
#include <functional>
#include <unordered_map>
class MyLambda {
public:
MyLambda() = default;
virtual ~MyLambda() = default;
};
template <typename T>
class HiddenLambda : public MyLambda {
static_assert(std::integral_constant<T, false>::value, "Template parameter needs to be of function type.");
};
template <typename Ret, typename... Args>
class HiddenLambda<Ret(Args...)> : public MyLambda {
public:
HiddenLambda(std::function<Ret(Args...)> _fun) : fun_(_fun) { }
Ret operator() (Args... args) {return fun_(args...);}
private:
std::function<Ret(Args...)> fun_;
};
int main() {
std::unordered_map<std::string, std::shared_ptr<MyLambda>> my_lambdas;
my_lambdas.insert(std::make_pair("fun1", std::shared_ptr<MyLambda>(
new HiddenLambda<size_t(std::string)>(
(std::string s) { return s.size(); } // <- lambda you want to store
)
)
));
my_lambdas.insert(std::make_pair("fun2", std::shared_ptr<MyLambda>(
new HiddenLambda<int(int)>(
(int x) { return x * 5; } // <- lambda you want to store
)
)
));
auto it = my_lambdas.find("fun1");
/* Get the function we want! */
std::shared_ptr<MyLambda> a_lam = it->second;
/* Need to know the types to actually use it though */
HiddenLambda<size_t(std::string)>& actual_lam = dynamic_cast<HiddenLambda<size_t(std::string)>&>(*a_lam);
std::cout << actual_lam("how long is this string?") << "n";
}
If this is what we really need to do, I suggest looking up various methods for type erasure.
I think the problem you are trying to solve probably has an easier solution. If you could give more details perhaps we could help?
EDIT
More relevant example to your provided code...
/* include above classes and includes */
void myfunc(int x, int y) {
std::cout << "uf1, " << x << ", " << y << std::endl;
}
int main() {
std::unordered_map<std::string, std::shared_ptr<MyLambda>> func_map;
func_map["userFun1"] = std::shared_ptr<MyLambda>(
new HiddenLambda<void(int, int)>( &myfunc ) // <- no args binded, notice the type = void(int,int)
);
func_map["userFun2"] = std::shared_ptr<MyLambda>(
new HiddenLambda<void(int)>( std::bind(myfunc, std::placeholders::_1, 5) ) // <- one args binded, notice the type = void(int)
);
func_map["userFun3"] = std::shared_ptr<MyLambda>(
new HiddenLambda<void()>( std::bind(myfunc, 1, 2)) // <- two args binded, notice the type = void()
);
/* we still need to know the type though,it will be either void(int, int), void(int) or void() */
HiddenLambda<void(int)>& actual_lam = dynamic_cast<HiddenLambda<void(int)>&>(*func_map["userFun2"]);
actual_lam(4);
}
EDIT V2
This is more of a guess then anything. I am not sure if you should do this (well definitely not outside of some interesting experimentation) or if it will even work. Here is a possible way if the amount different arguments for different functions is known and finite. This would require a technique called Library Interposing, which I do not know much about.
Firstly in the main program you define this enum and a factory function. The enum will describe every possible parameter range.
enum Types { kVOID, kINT_INT }; // <- verbosely define all the possible ones you would use
std::pair<Types, std::shared_ptr<MyLambda>> Factory(){
return
{
kVOID, /* <- some sensible default */
std::shared_ptr<MyLambda>(
new HiddenLambda<void()>( {} )
)
};
}
The shared library will have to provide an overriden factory method. Here is where I think you need the interposer to do so.
std::pair<Types, std::shared_ptr<MyLambda>> Factory(){
return
{
kVOID_INT_INT,
std::shared_ptr<MyLambda>(
new HiddenLambda<void(int, int)>( (int x, int y){ std::cout << (x + y);} )
)
};
}
Then the main method would look like:
int main() {
std::unordered_map<std::string, std::pair<Types, std::shared_ptr<MyLambda>>> func_map;
func_map.insert({"fun1", Factory()});
auto it = func_map.find("fun1");
/* always need to be able to deduce they type */
if (it->second.first == kVOID) {
CallHidden(*it->second.second);
}
else if (it->second.first == kINT_INT) {
CallHidden<int, int>(*it->second.second, 3, 4);
} else {
/* other ones you have statically typed */
}
}
Thestatic_assertonly covers view data types (what about floating point types? classes/structs?). Better: Just do not implement the template!
– Aconcagua
Nov 15 '18 at 6:52
Thanks for your answer. But it still need to know the type when get the function handle out from the map. It has the same limitation like usingstd::vector<std::any>. I have updated my question, do you have any other suggestion?
– J.Yang
Nov 15 '18 at 14:40
@J.Yang You always need to know the signature. At some point in your code you will need to give arguments to the function, at that point you need to know the types of all the arguments. I have added an edit that may help.
– Bar Stool
Nov 16 '18 at 7:08
@J.Yang Please let me know if you get it working, I am interested to know what you end up doing. It you are satisfied with this answer, please consider accepting it.
– Bar Stool
Nov 16 '18 at 7:38
@BarStool Thank you for your patient. I need think about your EDIT V2. If this does not work, I think I will fix the signature for the shared function. So it will accept multiple vectors. If I want send a few int inputs, I have to put them all in one vector<int>, and take them out at the beginning of the function.
– J.Yang
Nov 17 '18 at 0:13
add a comment |
It is possible but at some point you will need to know the return and parameter types.
You can use a type-erasure class to hide the return/parameter types and then store the type-erasure class. A naive implementation like this would suffice,
#include <iostream>
#include <functional>
#include <unordered_map>
class MyLambda {
public:
MyLambda() = default;
virtual ~MyLambda() = default;
};
template <typename T>
class HiddenLambda : public MyLambda {
static_assert(std::integral_constant<T, false>::value, "Template parameter needs to be of function type.");
};
template <typename Ret, typename... Args>
class HiddenLambda<Ret(Args...)> : public MyLambda {
public:
HiddenLambda(std::function<Ret(Args...)> _fun) : fun_(_fun) { }
Ret operator() (Args... args) {return fun_(args...);}
private:
std::function<Ret(Args...)> fun_;
};
int main() {
std::unordered_map<std::string, std::shared_ptr<MyLambda>> my_lambdas;
my_lambdas.insert(std::make_pair("fun1", std::shared_ptr<MyLambda>(
new HiddenLambda<size_t(std::string)>(
(std::string s) { return s.size(); } // <- lambda you want to store
)
)
));
my_lambdas.insert(std::make_pair("fun2", std::shared_ptr<MyLambda>(
new HiddenLambda<int(int)>(
(int x) { return x * 5; } // <- lambda you want to store
)
)
));
auto it = my_lambdas.find("fun1");
/* Get the function we want! */
std::shared_ptr<MyLambda> a_lam = it->second;
/* Need to know the types to actually use it though */
HiddenLambda<size_t(std::string)>& actual_lam = dynamic_cast<HiddenLambda<size_t(std::string)>&>(*a_lam);
std::cout << actual_lam("how long is this string?") << "n";
}
If this is what we really need to do, I suggest looking up various methods for type erasure.
I think the problem you are trying to solve probably has an easier solution. If you could give more details perhaps we could help?
EDIT
More relevant example to your provided code...
/* include above classes and includes */
void myfunc(int x, int y) {
std::cout << "uf1, " << x << ", " << y << std::endl;
}
int main() {
std::unordered_map<std::string, std::shared_ptr<MyLambda>> func_map;
func_map["userFun1"] = std::shared_ptr<MyLambda>(
new HiddenLambda<void(int, int)>( &myfunc ) // <- no args binded, notice the type = void(int,int)
);
func_map["userFun2"] = std::shared_ptr<MyLambda>(
new HiddenLambda<void(int)>( std::bind(myfunc, std::placeholders::_1, 5) ) // <- one args binded, notice the type = void(int)
);
func_map["userFun3"] = std::shared_ptr<MyLambda>(
new HiddenLambda<void()>( std::bind(myfunc, 1, 2)) // <- two args binded, notice the type = void()
);
/* we still need to know the type though,it will be either void(int, int), void(int) or void() */
HiddenLambda<void(int)>& actual_lam = dynamic_cast<HiddenLambda<void(int)>&>(*func_map["userFun2"]);
actual_lam(4);
}
EDIT V2
This is more of a guess then anything. I am not sure if you should do this (well definitely not outside of some interesting experimentation) or if it will even work. Here is a possible way if the amount different arguments for different functions is known and finite. This would require a technique called Library Interposing, which I do not know much about.
Firstly in the main program you define this enum and a factory function. The enum will describe every possible parameter range.
enum Types { kVOID, kINT_INT }; // <- verbosely define all the possible ones you would use
std::pair<Types, std::shared_ptr<MyLambda>> Factory(){
return
{
kVOID, /* <- some sensible default */
std::shared_ptr<MyLambda>(
new HiddenLambda<void()>( {} )
)
};
}
The shared library will have to provide an overriden factory method. Here is where I think you need the interposer to do so.
std::pair<Types, std::shared_ptr<MyLambda>> Factory(){
return
{
kVOID_INT_INT,
std::shared_ptr<MyLambda>(
new HiddenLambda<void(int, int)>( (int x, int y){ std::cout << (x + y);} )
)
};
}
Then the main method would look like:
int main() {
std::unordered_map<std::string, std::pair<Types, std::shared_ptr<MyLambda>>> func_map;
func_map.insert({"fun1", Factory()});
auto it = func_map.find("fun1");
/* always need to be able to deduce they type */
if (it->second.first == kVOID) {
CallHidden(*it->second.second);
}
else if (it->second.first == kINT_INT) {
CallHidden<int, int>(*it->second.second, 3, 4);
} else {
/* other ones you have statically typed */
}
}
It is possible but at some point you will need to know the return and parameter types.
You can use a type-erasure class to hide the return/parameter types and then store the type-erasure class. A naive implementation like this would suffice,
#include <iostream>
#include <functional>
#include <unordered_map>
class MyLambda {
public:
MyLambda() = default;
virtual ~MyLambda() = default;
};
template <typename T>
class HiddenLambda : public MyLambda {
static_assert(std::integral_constant<T, false>::value, "Template parameter needs to be of function type.");
};
template <typename Ret, typename... Args>
class HiddenLambda<Ret(Args...)> : public MyLambda {
public:
HiddenLambda(std::function<Ret(Args...)> _fun) : fun_(_fun) { }
Ret operator() (Args... args) {return fun_(args...);}
private:
std::function<Ret(Args...)> fun_;
};
int main() {
std::unordered_map<std::string, std::shared_ptr<MyLambda>> my_lambdas;
my_lambdas.insert(std::make_pair("fun1", std::shared_ptr<MyLambda>(
new HiddenLambda<size_t(std::string)>(
(std::string s) { return s.size(); } // <- lambda you want to store
)
)
));
my_lambdas.insert(std::make_pair("fun2", std::shared_ptr<MyLambda>(
new HiddenLambda<int(int)>(
(int x) { return x * 5; } // <- lambda you want to store
)
)
));
auto it = my_lambdas.find("fun1");
/* Get the function we want! */
std::shared_ptr<MyLambda> a_lam = it->second;
/* Need to know the types to actually use it though */
HiddenLambda<size_t(std::string)>& actual_lam = dynamic_cast<HiddenLambda<size_t(std::string)>&>(*a_lam);
std::cout << actual_lam("how long is this string?") << "n";
}
If this is what we really need to do, I suggest looking up various methods for type erasure.
I think the problem you are trying to solve probably has an easier solution. If you could give more details perhaps we could help?
EDIT
More relevant example to your provided code...
/* include above classes and includes */
void myfunc(int x, int y) {
std::cout << "uf1, " << x << ", " << y << std::endl;
}
int main() {
std::unordered_map<std::string, std::shared_ptr<MyLambda>> func_map;
func_map["userFun1"] = std::shared_ptr<MyLambda>(
new HiddenLambda<void(int, int)>( &myfunc ) // <- no args binded, notice the type = void(int,int)
);
func_map["userFun2"] = std::shared_ptr<MyLambda>(
new HiddenLambda<void(int)>( std::bind(myfunc, std::placeholders::_1, 5) ) // <- one args binded, notice the type = void(int)
);
func_map["userFun3"] = std::shared_ptr<MyLambda>(
new HiddenLambda<void()>( std::bind(myfunc, 1, 2)) // <- two args binded, notice the type = void()
);
/* we still need to know the type though,it will be either void(int, int), void(int) or void() */
HiddenLambda<void(int)>& actual_lam = dynamic_cast<HiddenLambda<void(int)>&>(*func_map["userFun2"]);
actual_lam(4);
}
EDIT V2
This is more of a guess then anything. I am not sure if you should do this (well definitely not outside of some interesting experimentation) or if it will even work. Here is a possible way if the amount different arguments for different functions is known and finite. This would require a technique called Library Interposing, which I do not know much about.
Firstly in the main program you define this enum and a factory function. The enum will describe every possible parameter range.
enum Types { kVOID, kINT_INT }; // <- verbosely define all the possible ones you would use
std::pair<Types, std::shared_ptr<MyLambda>> Factory(){
return
{
kVOID, /* <- some sensible default */
std::shared_ptr<MyLambda>(
new HiddenLambda<void()>( {} )
)
};
}
The shared library will have to provide an overriden factory method. Here is where I think you need the interposer to do so.
std::pair<Types, std::shared_ptr<MyLambda>> Factory(){
return
{
kVOID_INT_INT,
std::shared_ptr<MyLambda>(
new HiddenLambda<void(int, int)>( (int x, int y){ std::cout << (x + y);} )
)
};
}
Then the main method would look like:
int main() {
std::unordered_map<std::string, std::pair<Types, std::shared_ptr<MyLambda>>> func_map;
func_map.insert({"fun1", Factory()});
auto it = func_map.find("fun1");
/* always need to be able to deduce they type */
if (it->second.first == kVOID) {
CallHidden(*it->second.second);
}
else if (it->second.first == kINT_INT) {
CallHidden<int, int>(*it->second.second, 3, 4);
} else {
/* other ones you have statically typed */
}
}
edited Nov 16 '18 at 7:35
answered Nov 15 '18 at 6:17
Bar StoolBar Stool
1714
1714
Thestatic_assertonly covers view data types (what about floating point types? classes/structs?). Better: Just do not implement the template!
– Aconcagua
Nov 15 '18 at 6:52
Thanks for your answer. But it still need to know the type when get the function handle out from the map. It has the same limitation like usingstd::vector<std::any>. I have updated my question, do you have any other suggestion?
– J.Yang
Nov 15 '18 at 14:40
@J.Yang You always need to know the signature. At some point in your code you will need to give arguments to the function, at that point you need to know the types of all the arguments. I have added an edit that may help.
– Bar Stool
Nov 16 '18 at 7:08
@J.Yang Please let me know if you get it working, I am interested to know what you end up doing. It you are satisfied with this answer, please consider accepting it.
– Bar Stool
Nov 16 '18 at 7:38
@BarStool Thank you for your patient. I need think about your EDIT V2. If this does not work, I think I will fix the signature for the shared function. So it will accept multiple vectors. If I want send a few int inputs, I have to put them all in one vector<int>, and take them out at the beginning of the function.
– J.Yang
Nov 17 '18 at 0:13
add a comment |
Thestatic_assertonly covers view data types (what about floating point types? classes/structs?). Better: Just do not implement the template!
– Aconcagua
Nov 15 '18 at 6:52
Thanks for your answer. But it still need to know the type when get the function handle out from the map. It has the same limitation like usingstd::vector<std::any>. I have updated my question, do you have any other suggestion?
– J.Yang
Nov 15 '18 at 14:40
@J.Yang You always need to know the signature. At some point in your code you will need to give arguments to the function, at that point you need to know the types of all the arguments. I have added an edit that may help.
– Bar Stool
Nov 16 '18 at 7:08
@J.Yang Please let me know if you get it working, I am interested to know what you end up doing. It you are satisfied with this answer, please consider accepting it.
– Bar Stool
Nov 16 '18 at 7:38
@BarStool Thank you for your patient. I need think about your EDIT V2. If this does not work, I think I will fix the signature for the shared function. So it will accept multiple vectors. If I want send a few int inputs, I have to put them all in one vector<int>, and take them out at the beginning of the function.
– J.Yang
Nov 17 '18 at 0:13
The
static_assert only covers view data types (what about floating point types? classes/structs?). Better: Just do not implement the template!– Aconcagua
Nov 15 '18 at 6:52
The
static_assert only covers view data types (what about floating point types? classes/structs?). Better: Just do not implement the template!– Aconcagua
Nov 15 '18 at 6:52
Thanks for your answer. But it still need to know the type when get the function handle out from the map. It has the same limitation like using
std::vector<std::any>. I have updated my question, do you have any other suggestion?– J.Yang
Nov 15 '18 at 14:40
Thanks for your answer. But it still need to know the type when get the function handle out from the map. It has the same limitation like using
std::vector<std::any>. I have updated my question, do you have any other suggestion?– J.Yang
Nov 15 '18 at 14:40
@J.Yang You always need to know the signature. At some point in your code you will need to give arguments to the function, at that point you need to know the types of all the arguments. I have added an edit that may help.
– Bar Stool
Nov 16 '18 at 7:08
@J.Yang You always need to know the signature. At some point in your code you will need to give arguments to the function, at that point you need to know the types of all the arguments. I have added an edit that may help.
– Bar Stool
Nov 16 '18 at 7:08
@J.Yang Please let me know if you get it working, I am interested to know what you end up doing. It you are satisfied with this answer, please consider accepting it.
– Bar Stool
Nov 16 '18 at 7:38
@J.Yang Please let me know if you get it working, I am interested to know what you end up doing. It you are satisfied with this answer, please consider accepting it.
– Bar Stool
Nov 16 '18 at 7:38
@BarStool Thank you for your patient. I need think about your EDIT V2. If this does not work, I think I will fix the signature for the shared function. So it will accept multiple vectors. If I want send a few int inputs, I have to put them all in one vector<int>, and take them out at the beginning of the function.
– J.Yang
Nov 17 '18 at 0:13
@BarStool Thank you for your patient. I need think about your EDIT V2. If this does not work, I think I will fix the signature for the shared function. So it will accept multiple vectors. If I want send a few int inputs, I have to put them all in one vector<int>, and take them out at the beginning of the function.
– J.Yang
Nov 17 '18 at 0:13
add a comment |
If at time of creating object of std::function<void()>, you know function signature then you may be able to do like below.
#include <iostream>
#include <functional>
#include <unordered_map>
void userFun1 (int i1, int i2)
{
std::cout << "uf1, " << i1 << ", " << i2 << std::endl;
}
int main()
{
std::unordered_map<std::string, std::function<void()>> func_map;
func_map["userFun1"] = std::bind(userFun1,1,2);
func_map["userFun1"]();
int i1{2},i2{3};
func_map["userFun1.1"] = std::bind(userFun1,std::ref(i1),std::ref(i2));
func_map["userFun1.1"]();
i1 = 3;
i2 = 4;
func_map["userFun1.1"]();
return 0;
}
Live Code
Thanks for your answer. That std::ref sounds like the tricky. I have updated my question, do you think this can be a workaround?
– J.Yang
Nov 15 '18 at 14:37
@J.Yang For your update,I don't think that may be possible. For any plugin system, there is fixed set of function call OR API which are know to both plugin loader and plugin it self. In your case you can create wrapper of your client code which know what are signature of client function and what are value need to pass to client function and call this wrapper function from your server code. Hope this will help!
– Manthan Tilva
Nov 16 '18 at 5:23
add a comment |
If at time of creating object of std::function<void()>, you know function signature then you may be able to do like below.
#include <iostream>
#include <functional>
#include <unordered_map>
void userFun1 (int i1, int i2)
{
std::cout << "uf1, " << i1 << ", " << i2 << std::endl;
}
int main()
{
std::unordered_map<std::string, std::function<void()>> func_map;
func_map["userFun1"] = std::bind(userFun1,1,2);
func_map["userFun1"]();
int i1{2},i2{3};
func_map["userFun1.1"] = std::bind(userFun1,std::ref(i1),std::ref(i2));
func_map["userFun1.1"]();
i1 = 3;
i2 = 4;
func_map["userFun1.1"]();
return 0;
}
Live Code
Thanks for your answer. That std::ref sounds like the tricky. I have updated my question, do you think this can be a workaround?
– J.Yang
Nov 15 '18 at 14:37
@J.Yang For your update,I don't think that may be possible. For any plugin system, there is fixed set of function call OR API which are know to both plugin loader and plugin it self. In your case you can create wrapper of your client code which know what are signature of client function and what are value need to pass to client function and call this wrapper function from your server code. Hope this will help!
– Manthan Tilva
Nov 16 '18 at 5:23
add a comment |
If at time of creating object of std::function<void()>, you know function signature then you may be able to do like below.
#include <iostream>
#include <functional>
#include <unordered_map>
void userFun1 (int i1, int i2)
{
std::cout << "uf1, " << i1 << ", " << i2 << std::endl;
}
int main()
{
std::unordered_map<std::string, std::function<void()>> func_map;
func_map["userFun1"] = std::bind(userFun1,1,2);
func_map["userFun1"]();
int i1{2},i2{3};
func_map["userFun1.1"] = std::bind(userFun1,std::ref(i1),std::ref(i2));
func_map["userFun1.1"]();
i1 = 3;
i2 = 4;
func_map["userFun1.1"]();
return 0;
}
Live Code
If at time of creating object of std::function<void()>, you know function signature then you may be able to do like below.
#include <iostream>
#include <functional>
#include <unordered_map>
void userFun1 (int i1, int i2)
{
std::cout << "uf1, " << i1 << ", " << i2 << std::endl;
}
int main()
{
std::unordered_map<std::string, std::function<void()>> func_map;
func_map["userFun1"] = std::bind(userFun1,1,2);
func_map["userFun1"]();
int i1{2},i2{3};
func_map["userFun1.1"] = std::bind(userFun1,std::ref(i1),std::ref(i2));
func_map["userFun1.1"]();
i1 = 3;
i2 = 4;
func_map["userFun1.1"]();
return 0;
}
Live Code
answered Nov 15 '18 at 5:54
Manthan TilvaManthan Tilva
1,306823
1,306823
Thanks for your answer. That std::ref sounds like the tricky. I have updated my question, do you think this can be a workaround?
– J.Yang
Nov 15 '18 at 14:37
@J.Yang For your update,I don't think that may be possible. For any plugin system, there is fixed set of function call OR API which are know to both plugin loader and plugin it self. In your case you can create wrapper of your client code which know what are signature of client function and what are value need to pass to client function and call this wrapper function from your server code. Hope this will help!
– Manthan Tilva
Nov 16 '18 at 5:23
add a comment |
Thanks for your answer. That std::ref sounds like the tricky. I have updated my question, do you think this can be a workaround?
– J.Yang
Nov 15 '18 at 14:37
@J.Yang For your update,I don't think that may be possible. For any plugin system, there is fixed set of function call OR API which are know to both plugin loader and plugin it self. In your case you can create wrapper of your client code which know what are signature of client function and what are value need to pass to client function and call this wrapper function from your server code. Hope this will help!
– Manthan Tilva
Nov 16 '18 at 5:23
Thanks for your answer. That std::ref sounds like the tricky. I have updated my question, do you think this can be a workaround?
– J.Yang
Nov 15 '18 at 14:37
Thanks for your answer. That std::ref sounds like the tricky. I have updated my question, do you think this can be a workaround?
– J.Yang
Nov 15 '18 at 14:37
@J.Yang For your update,I don't think that may be possible. For any plugin system, there is fixed set of function call OR API which are know to both plugin loader and plugin it self. In your case you can create wrapper of your client code which know what are signature of client function and what are value need to pass to client function and call this wrapper function from your server code. Hope this will help!
– Manthan Tilva
Nov 16 '18 at 5:23
@J.Yang For your update,I don't think that may be possible. For any plugin system, there is fixed set of function call OR API which are know to both plugin loader and plugin it self. In your case you can create wrapper of your client code which know what are signature of client function and what are value need to pass to client function and call this wrapper function from your server code. Hope this will help!
– Manthan Tilva
Nov 16 '18 at 5:23
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53312744%2fc-build-a-name-to-function-table-functions-have-different-signature%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
5
Why do you think you need this? Sounds like and XY problem to me. What is the underlying problem you are trying to solve?
– super
Nov 15 '18 at 5:11
7
After you retrieve a function from the map, how will you know what its signature is?
– Raymond Chen
Nov 15 '18 at 5:13
@RaymondChen I think you are right. C++ is a language needs to know type at compilation.
– J.Yang
Nov 15 '18 at 14:30
I have updated my question, @super, thanks for your comment
– J.Yang
Nov 15 '18 at 14:31
If you know the signature at compile time (e.g. "The item named
bobis always avoid(*)(int,int)") then you can cast a plain function pointer tovoid(*)()for storage, then cast it tovoid(*)(int,int)after retrieving. Function pointers of different signature can be interconverted without loss of fidelity, but you have to cast back to the original type before using them to call the function. If you cast to the wrong signature and then try to call the function, the result is undefined (i.e., "bad").– Raymond Chen
Nov 15 '18 at 15:37