How do I create an array of function pointers of different prototypes?











up vote
27
down vote

favorite
3












I have a few functions defined like this:



ParentClass*    fun1();
ParentClass* fun2();
ParentClass* fun3(bool inp=false);
ChildClass* fun4();
ChildClass* fun5(int a=1, int b=3);


I would like to put them into an array of some kind as follows:



void* (*arr[5])() = {
(void* (*)())fun1,
(void* (*)())fun2,
(void* (*)())fun3,
(void* (*)())fun4,
(void* (*)())fun5
}


Now I would like to use this array of functions simply as



for(int i=0; i<5; i++)
someFunction(arr[i]());


Now I realize here that the issue is void* (*arr[5])(), but given that I only want to use the functions without supplying an argument, I would like all of these to be part of the same array.



These are very C-style ways to do it, though. Is there a better way to do it using Templates in C++?










share|improve this question
























  • Why do you want to discard the type from the return? does ChildClass not inherit ParentClass?
    – Caleth
    Dec 5 at 9:47










  • When I use it, I am actually casting it to ParentClass. I could make this a ParentClass* instead of void*, but that way I would have to type cast each entry into the array. I instead currently choose to cast it after I retrieve it from the array.
    – vc669
    Dec 5 at 10:00










  • I miscommunicated through the question that I didn't want to use. I do want to use it. Modified the question accordingly.
    – vc669
    Dec 5 at 10:32










  • In your first snippet you have declared fun4 twice, is that a typo?
    – Fabio Turati
    Dec 5 at 13:48










  • Yup. Corrected.
    – vc669
    Dec 5 at 17:16















up vote
27
down vote

favorite
3












I have a few functions defined like this:



ParentClass*    fun1();
ParentClass* fun2();
ParentClass* fun3(bool inp=false);
ChildClass* fun4();
ChildClass* fun5(int a=1, int b=3);


I would like to put them into an array of some kind as follows:



void* (*arr[5])() = {
(void* (*)())fun1,
(void* (*)())fun2,
(void* (*)())fun3,
(void* (*)())fun4,
(void* (*)())fun5
}


Now I would like to use this array of functions simply as



for(int i=0; i<5; i++)
someFunction(arr[i]());


Now I realize here that the issue is void* (*arr[5])(), but given that I only want to use the functions without supplying an argument, I would like all of these to be part of the same array.



These are very C-style ways to do it, though. Is there a better way to do it using Templates in C++?










share|improve this question
























  • Why do you want to discard the type from the return? does ChildClass not inherit ParentClass?
    – Caleth
    Dec 5 at 9:47










  • When I use it, I am actually casting it to ParentClass. I could make this a ParentClass* instead of void*, but that way I would have to type cast each entry into the array. I instead currently choose to cast it after I retrieve it from the array.
    – vc669
    Dec 5 at 10:00










  • I miscommunicated through the question that I didn't want to use. I do want to use it. Modified the question accordingly.
    – vc669
    Dec 5 at 10:32










  • In your first snippet you have declared fun4 twice, is that a typo?
    – Fabio Turati
    Dec 5 at 13:48










  • Yup. Corrected.
    – vc669
    Dec 5 at 17:16













up vote
27
down vote

favorite
3









up vote
27
down vote

favorite
3






3





I have a few functions defined like this:



ParentClass*    fun1();
ParentClass* fun2();
ParentClass* fun3(bool inp=false);
ChildClass* fun4();
ChildClass* fun5(int a=1, int b=3);


I would like to put them into an array of some kind as follows:



void* (*arr[5])() = {
(void* (*)())fun1,
(void* (*)())fun2,
(void* (*)())fun3,
(void* (*)())fun4,
(void* (*)())fun5
}


Now I would like to use this array of functions simply as



for(int i=0; i<5; i++)
someFunction(arr[i]());


Now I realize here that the issue is void* (*arr[5])(), but given that I only want to use the functions without supplying an argument, I would like all of these to be part of the same array.



These are very C-style ways to do it, though. Is there a better way to do it using Templates in C++?










share|improve this question















I have a few functions defined like this:



ParentClass*    fun1();
ParentClass* fun2();
ParentClass* fun3(bool inp=false);
ChildClass* fun4();
ChildClass* fun5(int a=1, int b=3);


I would like to put them into an array of some kind as follows:



void* (*arr[5])() = {
(void* (*)())fun1,
(void* (*)())fun2,
(void* (*)())fun3,
(void* (*)())fun4,
(void* (*)())fun5
}


Now I would like to use this array of functions simply as



for(int i=0; i<5; i++)
someFunction(arr[i]());


Now I realize here that the issue is void* (*arr[5])(), but given that I only want to use the functions without supplying an argument, I would like all of these to be part of the same array.



These are very C-style ways to do it, though. Is there a better way to do it using Templates in C++?







c++ function oop c++14






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Dec 5 at 17:15

























asked Dec 5 at 9:15









vc669

31628




31628












  • Why do you want to discard the type from the return? does ChildClass not inherit ParentClass?
    – Caleth
    Dec 5 at 9:47










  • When I use it, I am actually casting it to ParentClass. I could make this a ParentClass* instead of void*, but that way I would have to type cast each entry into the array. I instead currently choose to cast it after I retrieve it from the array.
    – vc669
    Dec 5 at 10:00










  • I miscommunicated through the question that I didn't want to use. I do want to use it. Modified the question accordingly.
    – vc669
    Dec 5 at 10:32










  • In your first snippet you have declared fun4 twice, is that a typo?
    – Fabio Turati
    Dec 5 at 13:48










  • Yup. Corrected.
    – vc669
    Dec 5 at 17:16


















  • Why do you want to discard the type from the return? does ChildClass not inherit ParentClass?
    – Caleth
    Dec 5 at 9:47










  • When I use it, I am actually casting it to ParentClass. I could make this a ParentClass* instead of void*, but that way I would have to type cast each entry into the array. I instead currently choose to cast it after I retrieve it from the array.
    – vc669
    Dec 5 at 10:00










  • I miscommunicated through the question that I didn't want to use. I do want to use it. Modified the question accordingly.
    – vc669
    Dec 5 at 10:32










  • In your first snippet you have declared fun4 twice, is that a typo?
    – Fabio Turati
    Dec 5 at 13:48










  • Yup. Corrected.
    – vc669
    Dec 5 at 17:16
















Why do you want to discard the type from the return? does ChildClass not inherit ParentClass?
– Caleth
Dec 5 at 9:47




Why do you want to discard the type from the return? does ChildClass not inherit ParentClass?
– Caleth
Dec 5 at 9:47












When I use it, I am actually casting it to ParentClass. I could make this a ParentClass* instead of void*, but that way I would have to type cast each entry into the array. I instead currently choose to cast it after I retrieve it from the array.
– vc669
Dec 5 at 10:00




When I use it, I am actually casting it to ParentClass. I could make this a ParentClass* instead of void*, but that way I would have to type cast each entry into the array. I instead currently choose to cast it after I retrieve it from the array.
– vc669
Dec 5 at 10:00












I miscommunicated through the question that I didn't want to use. I do want to use it. Modified the question accordingly.
– vc669
Dec 5 at 10:32




I miscommunicated through the question that I didn't want to use. I do want to use it. Modified the question accordingly.
– vc669
Dec 5 at 10:32












In your first snippet you have declared fun4 twice, is that a typo?
– Fabio Turati
Dec 5 at 13:48




In your first snippet you have declared fun4 twice, is that a typo?
– Fabio Turati
Dec 5 at 13:48












Yup. Corrected.
– vc669
Dec 5 at 17:16




Yup. Corrected.
– vc669
Dec 5 at 17:16












5 Answers
5






active

oldest

votes

















up vote
40
down vote



accepted










C-style or not, what you have is straight undefined behaviour. Use lambdas:



void (*arr[5])() = {
{ fun1(); },
{ fun2(); },
{ fun3(); },
{ fun4(); },
{ fun5(); }
};


These are okay because they perform the call through the function's correct type, and are themselves convertible to void (*)().



Forwarding the returned value stays simple enough, since the lambda provides a context for the conversion. In your case, since ChildClass supposedly inherits from ParentClass, an implicit conversion is enough:



ParentClass *(*arr[5])() = {
() -> ParentClass * { return fun1(); },
() -> ParentClass * { return fun2(); },
() -> ParentClass * { return fun3(); },
() -> ParentClass * { return fun4(); },
() -> ParentClass * { return fun5(); }
};





share|improve this answer























  • Does this make the return type of the functions void?
    – vc669
    Dec 5 at 10:14










  • @vc669 Yes, since you don't use it anyway. However, you can also use the lambdas to reconcile the return types, which since I guess ChildClass inherits from ParentClass is just () -> ParentClasss * { return fun1(); }.
    – Quentin
    Dec 5 at 10:18








  • 1




    Actually, one would only need lambdas for fun3 and fun5...
    – Aconcagua
    Dec 5 at 12:08






  • 1




    @Aconcagua yes, but consistency. One could avoid repetition by using a function that takes in all of the fun*'s at once and returns the array of wrapped functions as well.
    – Quentin
    Dec 5 at 12:18








  • 1




    @Aconcagua Almost: it gets compiled into a single jmp. Although the function's body will be inlined into the lambda if applicable.
    – Quentin
    Dec 5 at 12:33


















up vote
15
down vote














but given that I only want to use the functions without supplying an argument




It simply doesn't work like that. Did you ever wonder, then when you're put function declarations in a header, why you have to write default parameters into the header and can not place it in the definition in the implementation source file?



That's because the default parameters are in fact not "embedded" into the function, but used by the compiler to augment a function call with those parameters at a calling location, where those parameters are omitted. (EDIT: Also, as @Aconcagua so keenly observed in a comment, since default parameters are usually defined as part of a header function declaration, any change of the default values requires a full recompilation of any compilation unit that included those headers, ergo function declarations, for the change to actually take effect!)



While it's perfectly possible to do some really weird type casting madness to construct an array of function pointers like that, eventually you'll have to cast back to the original function call signature in order to not invoke undefined behavior.



If anything you'll have to bind the function pointer, together with a set of default parameters in some type that abstracts away the calling, does supply the parameters and to the outside offers a polymorphic interface. So you'd have a std::vector<function_binder> or function_binder where function binder has a operator() that calls the function.



But when you're doing binding in the first place, you can bind it in an anonymous function, i.e. lambdas. At the time of lambda instanciation the default parameters are bound.



std::vector<void(*)()> fvec = {
{ func0(); },
{ func1(); },
{ func2(); },
}





share|improve this answer























  • Might be worth to mention that, as parameters are provided in header, if changing these, any translation units relying on need to be re-compiled to make these changes effective there as well...
    – Aconcagua
    Dec 5 at 12:13










  • @Aconcagua: That's a very good point!
    – datenwolf
    Dec 5 at 12:55


















up vote
9
down vote













You can use std::bind



std::function<ParentClass *(void)> arr[5] = {
std::bind(&fun1),
std::bind(&fun2),
std::bind(&fun3, false),
std::bind(&fun4),
std::bind(&fun5, 1, 3)
};


now you can do



for(int i=0; i<5; i++)
arr[i]();


You have to make sure every function parameter of all functions are bound.



This also works well with member functions. You just have to bind the object reference (e.g. this) as first parameter.






share|improve this answer



















  • 1




    since C++11 and above there is no point to use bind since lambda is more handy and faster.
    – Marek R
    Dec 5 at 9:42












  • @Marek R - Depending on implementation std::bind might just return an lambda because it's return type is unspecified. It's probably just a matter of taste which one you use.
    – Detonar
    Dec 5 at 9:47






  • 2




    My taste says std::bind since if forces less disciplined developer to write small functions. Lambda is often overused and grows to ridicules sizes, but still it is easier to use and it is faster. std::bind creates complex templates which is annoying when analyzing a crash logs.
    – Marek R
    Dec 5 at 9:51












  • This does not compile.
    – Quentin
    Dec 5 at 9:55










  • @Quentin - Thanks. Of course you can't have an array of auto. I corrected that.
    – Detonar
    Dec 5 at 10:08


















up vote
3
down vote













A c++20 solution:



#define RETURNS(...) 
noexcept(noexcept(__VA_ARGS__))
-> decltype(__VA_ARGS__)
{ return __VA_ARGS__; }


template<auto f, class R, class...Args>
struct explicit_function_caster {
using Sig=R(Args...);
using pSig=Sig*;
constexpr operator pSig()const {
return (Args...args)->R {
return static_cast<R>(f(std::forward<Args>(args)...));
};
}
};

template<auto f>
struct overload_storer_t {
template<class R, class...Args>
constexpr (*operator R() const)(Args...) const {
return explicit_function_caster<f, R, Args...>{};
}
template<class...Args>
auto operator()(Args&&...args)
RETURNS( f( std::forward<Args>(args)... ) )
};
template<auto f>
overload_storer_t<f> generate_overloads={};

#define OVERLOADS_OF(...)
generate_overloads<
(auto&&...args)
RETURNS( __VA_ARGS__( decltype(args)(args)... ) )
>


which is a lot of boilerplate, but gets us:



ParentClass* (*arr[5])() = {
OVERLOADS_OF(fun1),
OVERLOADS_OF(fun2),
OVERLOADS_OF(fun3),
OVERLOADS_OF(fun4),
OVERLOADS_OF(fun5)
};
void (*arr2[5])() = {
OVERLOADS_OF(fun1),
OVERLOADS_OF(fun2),
OVERLOADS_OF(fun3),
OVERLOADS_OF(fun4),
OVERLOADS_OF(fun5)
};


basically generate_overloads<x> takes a constexpr callable object x and lets you cast it at compile time to a pointer to a function of any compatible signature and call it with (almost) any signature.



Meanwhile, OVERLOADS_OF converts a function name into a constexpr object that does overload resolution on that function name. I use it here because fun3 as a function pointer does not know about its default arguments, but at overload resolution time it does.



In this particular case, it is far easier to just write toy lambdas to do this work; this is just an attempt to automate writing those toy lambdas for arbitrary compatible signatures.






share|improve this answer























  • constexpr (*operator R() const)(Args...) const oh what the hell... Also, is decltype(args)(args)... a replacement for std::forward or is there additional subtlety?
    – Quentin
    Dec 5 at 20:56










  • @Quentin Yes. I don't have the type of args. The cast operator was there because the C++2a compilers didn't like auto based partial specialization, so I couldn't easily unpack a Sig: that is a type-deduced conversion operator to function pointer.
    – Yakk - Adam Nevraumont
    Dec 5 at 21:06










  • I can't fathom why there are two consts in there though...
    – Quentin
    Dec 5 at 21:41






  • 1




    @Quentin Laugh, I think I converted to a const function pointer in a const method. Accidentally: the fact the function pointer is const is pointless.
    – Yakk - Adam Nevraumont
    Dec 5 at 22:04




















up vote
1
down vote













Since you have tagged question with C++14 you should not use function pointers!



With C++14 you should prefer std::function and lambadas.



Also you should not use C style array, but only std::array and/or std::vector.



Also avoid raw pointers, use std::unique_ptr and std::shared_ptr.



So simplest and best whay to solve it is:



std::array<std::function<ParentClass*()>,5> arr {
() { return fun1(); },
() { return fun2(); },
() { return fun3(true); },
() { return fun4(); },
() { return fun5(7, 9); }
};


Why not simple array of pointers like in @Quentin answer? He used lambdas, but he can't use lambda which binds anything (if you need to).






share|improve this answer



















  • 2




    Downvoted because std::function is a heavyweight facility, and the problem at hand does not require any of the functionality it provides over plain function pointers.
    – Quentin
    Dec 5 at 9:54






  • 7




    I'm tempted to give an upvote for "Lambadas" :)
    – Willem van Rumpt
    Dec 5 at 10:08











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',
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
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53628791%2fhow-do-i-create-an-array-of-function-pointers-of-different-prototypes%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























5 Answers
5






active

oldest

votes








5 Answers
5






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
40
down vote



accepted










C-style or not, what you have is straight undefined behaviour. Use lambdas:



void (*arr[5])() = {
{ fun1(); },
{ fun2(); },
{ fun3(); },
{ fun4(); },
{ fun5(); }
};


These are okay because they perform the call through the function's correct type, and are themselves convertible to void (*)().



Forwarding the returned value stays simple enough, since the lambda provides a context for the conversion. In your case, since ChildClass supposedly inherits from ParentClass, an implicit conversion is enough:



ParentClass *(*arr[5])() = {
() -> ParentClass * { return fun1(); },
() -> ParentClass * { return fun2(); },
() -> ParentClass * { return fun3(); },
() -> ParentClass * { return fun4(); },
() -> ParentClass * { return fun5(); }
};





share|improve this answer























  • Does this make the return type of the functions void?
    – vc669
    Dec 5 at 10:14










  • @vc669 Yes, since you don't use it anyway. However, you can also use the lambdas to reconcile the return types, which since I guess ChildClass inherits from ParentClass is just () -> ParentClasss * { return fun1(); }.
    – Quentin
    Dec 5 at 10:18








  • 1




    Actually, one would only need lambdas for fun3 and fun5...
    – Aconcagua
    Dec 5 at 12:08






  • 1




    @Aconcagua yes, but consistency. One could avoid repetition by using a function that takes in all of the fun*'s at once and returns the array of wrapped functions as well.
    – Quentin
    Dec 5 at 12:18








  • 1




    @Aconcagua Almost: it gets compiled into a single jmp. Although the function's body will be inlined into the lambda if applicable.
    – Quentin
    Dec 5 at 12:33















up vote
40
down vote



accepted










C-style or not, what you have is straight undefined behaviour. Use lambdas:



void (*arr[5])() = {
{ fun1(); },
{ fun2(); },
{ fun3(); },
{ fun4(); },
{ fun5(); }
};


These are okay because they perform the call through the function's correct type, and are themselves convertible to void (*)().



Forwarding the returned value stays simple enough, since the lambda provides a context for the conversion. In your case, since ChildClass supposedly inherits from ParentClass, an implicit conversion is enough:



ParentClass *(*arr[5])() = {
() -> ParentClass * { return fun1(); },
() -> ParentClass * { return fun2(); },
() -> ParentClass * { return fun3(); },
() -> ParentClass * { return fun4(); },
() -> ParentClass * { return fun5(); }
};





share|improve this answer























  • Does this make the return type of the functions void?
    – vc669
    Dec 5 at 10:14










  • @vc669 Yes, since you don't use it anyway. However, you can also use the lambdas to reconcile the return types, which since I guess ChildClass inherits from ParentClass is just () -> ParentClasss * { return fun1(); }.
    – Quentin
    Dec 5 at 10:18








  • 1




    Actually, one would only need lambdas for fun3 and fun5...
    – Aconcagua
    Dec 5 at 12:08






  • 1




    @Aconcagua yes, but consistency. One could avoid repetition by using a function that takes in all of the fun*'s at once and returns the array of wrapped functions as well.
    – Quentin
    Dec 5 at 12:18








  • 1




    @Aconcagua Almost: it gets compiled into a single jmp. Although the function's body will be inlined into the lambda if applicable.
    – Quentin
    Dec 5 at 12:33













up vote
40
down vote



accepted







up vote
40
down vote



accepted






C-style or not, what you have is straight undefined behaviour. Use lambdas:



void (*arr[5])() = {
{ fun1(); },
{ fun2(); },
{ fun3(); },
{ fun4(); },
{ fun5(); }
};


These are okay because they perform the call through the function's correct type, and are themselves convertible to void (*)().



Forwarding the returned value stays simple enough, since the lambda provides a context for the conversion. In your case, since ChildClass supposedly inherits from ParentClass, an implicit conversion is enough:



ParentClass *(*arr[5])() = {
() -> ParentClass * { return fun1(); },
() -> ParentClass * { return fun2(); },
() -> ParentClass * { return fun3(); },
() -> ParentClass * { return fun4(); },
() -> ParentClass * { return fun5(); }
};





share|improve this answer














C-style or not, what you have is straight undefined behaviour. Use lambdas:



void (*arr[5])() = {
{ fun1(); },
{ fun2(); },
{ fun3(); },
{ fun4(); },
{ fun5(); }
};


These are okay because they perform the call through the function's correct type, and are themselves convertible to void (*)().



Forwarding the returned value stays simple enough, since the lambda provides a context for the conversion. In your case, since ChildClass supposedly inherits from ParentClass, an implicit conversion is enough:



ParentClass *(*arr[5])() = {
() -> ParentClass * { return fun1(); },
() -> ParentClass * { return fun2(); },
() -> ParentClass * { return fun3(); },
() -> ParentClass * { return fun4(); },
() -> ParentClass * { return fun5(); }
};






share|improve this answer














share|improve this answer



share|improve this answer








edited Dec 5 at 10:34

























answered Dec 5 at 9:18









Quentin

44.3k584140




44.3k584140












  • Does this make the return type of the functions void?
    – vc669
    Dec 5 at 10:14










  • @vc669 Yes, since you don't use it anyway. However, you can also use the lambdas to reconcile the return types, which since I guess ChildClass inherits from ParentClass is just () -> ParentClasss * { return fun1(); }.
    – Quentin
    Dec 5 at 10:18








  • 1




    Actually, one would only need lambdas for fun3 and fun5...
    – Aconcagua
    Dec 5 at 12:08






  • 1




    @Aconcagua yes, but consistency. One could avoid repetition by using a function that takes in all of the fun*'s at once and returns the array of wrapped functions as well.
    – Quentin
    Dec 5 at 12:18








  • 1




    @Aconcagua Almost: it gets compiled into a single jmp. Although the function's body will be inlined into the lambda if applicable.
    – Quentin
    Dec 5 at 12:33


















  • Does this make the return type of the functions void?
    – vc669
    Dec 5 at 10:14










  • @vc669 Yes, since you don't use it anyway. However, you can also use the lambdas to reconcile the return types, which since I guess ChildClass inherits from ParentClass is just () -> ParentClasss * { return fun1(); }.
    – Quentin
    Dec 5 at 10:18








  • 1




    Actually, one would only need lambdas for fun3 and fun5...
    – Aconcagua
    Dec 5 at 12:08






  • 1




    @Aconcagua yes, but consistency. One could avoid repetition by using a function that takes in all of the fun*'s at once and returns the array of wrapped functions as well.
    – Quentin
    Dec 5 at 12:18








  • 1




    @Aconcagua Almost: it gets compiled into a single jmp. Although the function's body will be inlined into the lambda if applicable.
    – Quentin
    Dec 5 at 12:33
















Does this make the return type of the functions void?
– vc669
Dec 5 at 10:14




Does this make the return type of the functions void?
– vc669
Dec 5 at 10:14












@vc669 Yes, since you don't use it anyway. However, you can also use the lambdas to reconcile the return types, which since I guess ChildClass inherits from ParentClass is just () -> ParentClasss * { return fun1(); }.
– Quentin
Dec 5 at 10:18






@vc669 Yes, since you don't use it anyway. However, you can also use the lambdas to reconcile the return types, which since I guess ChildClass inherits from ParentClass is just () -> ParentClasss * { return fun1(); }.
– Quentin
Dec 5 at 10:18






1




1




Actually, one would only need lambdas for fun3 and fun5...
– Aconcagua
Dec 5 at 12:08




Actually, one would only need lambdas for fun3 and fun5...
– Aconcagua
Dec 5 at 12:08




1




1




@Aconcagua yes, but consistency. One could avoid repetition by using a function that takes in all of the fun*'s at once and returns the array of wrapped functions as well.
– Quentin
Dec 5 at 12:18






@Aconcagua yes, but consistency. One could avoid repetition by using a function that takes in all of the fun*'s at once and returns the array of wrapped functions as well.
– Quentin
Dec 5 at 12:18






1




1




@Aconcagua Almost: it gets compiled into a single jmp. Although the function's body will be inlined into the lambda if applicable.
– Quentin
Dec 5 at 12:33




@Aconcagua Almost: it gets compiled into a single jmp. Although the function's body will be inlined into the lambda if applicable.
– Quentin
Dec 5 at 12:33












up vote
15
down vote














but given that I only want to use the functions without supplying an argument




It simply doesn't work like that. Did you ever wonder, then when you're put function declarations in a header, why you have to write default parameters into the header and can not place it in the definition in the implementation source file?



That's because the default parameters are in fact not "embedded" into the function, but used by the compiler to augment a function call with those parameters at a calling location, where those parameters are omitted. (EDIT: Also, as @Aconcagua so keenly observed in a comment, since default parameters are usually defined as part of a header function declaration, any change of the default values requires a full recompilation of any compilation unit that included those headers, ergo function declarations, for the change to actually take effect!)



While it's perfectly possible to do some really weird type casting madness to construct an array of function pointers like that, eventually you'll have to cast back to the original function call signature in order to not invoke undefined behavior.



If anything you'll have to bind the function pointer, together with a set of default parameters in some type that abstracts away the calling, does supply the parameters and to the outside offers a polymorphic interface. So you'd have a std::vector<function_binder> or function_binder where function binder has a operator() that calls the function.



But when you're doing binding in the first place, you can bind it in an anonymous function, i.e. lambdas. At the time of lambda instanciation the default parameters are bound.



std::vector<void(*)()> fvec = {
{ func0(); },
{ func1(); },
{ func2(); },
}





share|improve this answer























  • Might be worth to mention that, as parameters are provided in header, if changing these, any translation units relying on need to be re-compiled to make these changes effective there as well...
    – Aconcagua
    Dec 5 at 12:13










  • @Aconcagua: That's a very good point!
    – datenwolf
    Dec 5 at 12:55















up vote
15
down vote














but given that I only want to use the functions without supplying an argument




It simply doesn't work like that. Did you ever wonder, then when you're put function declarations in a header, why you have to write default parameters into the header and can not place it in the definition in the implementation source file?



That's because the default parameters are in fact not "embedded" into the function, but used by the compiler to augment a function call with those parameters at a calling location, where those parameters are omitted. (EDIT: Also, as @Aconcagua so keenly observed in a comment, since default parameters are usually defined as part of a header function declaration, any change of the default values requires a full recompilation of any compilation unit that included those headers, ergo function declarations, for the change to actually take effect!)



While it's perfectly possible to do some really weird type casting madness to construct an array of function pointers like that, eventually you'll have to cast back to the original function call signature in order to not invoke undefined behavior.



If anything you'll have to bind the function pointer, together with a set of default parameters in some type that abstracts away the calling, does supply the parameters and to the outside offers a polymorphic interface. So you'd have a std::vector<function_binder> or function_binder where function binder has a operator() that calls the function.



But when you're doing binding in the first place, you can bind it in an anonymous function, i.e. lambdas. At the time of lambda instanciation the default parameters are bound.



std::vector<void(*)()> fvec = {
{ func0(); },
{ func1(); },
{ func2(); },
}





share|improve this answer























  • Might be worth to mention that, as parameters are provided in header, if changing these, any translation units relying on need to be re-compiled to make these changes effective there as well...
    – Aconcagua
    Dec 5 at 12:13










  • @Aconcagua: That's a very good point!
    – datenwolf
    Dec 5 at 12:55













up vote
15
down vote










up vote
15
down vote










but given that I only want to use the functions without supplying an argument




It simply doesn't work like that. Did you ever wonder, then when you're put function declarations in a header, why you have to write default parameters into the header and can not place it in the definition in the implementation source file?



That's because the default parameters are in fact not "embedded" into the function, but used by the compiler to augment a function call with those parameters at a calling location, where those parameters are omitted. (EDIT: Also, as @Aconcagua so keenly observed in a comment, since default parameters are usually defined as part of a header function declaration, any change of the default values requires a full recompilation of any compilation unit that included those headers, ergo function declarations, for the change to actually take effect!)



While it's perfectly possible to do some really weird type casting madness to construct an array of function pointers like that, eventually you'll have to cast back to the original function call signature in order to not invoke undefined behavior.



If anything you'll have to bind the function pointer, together with a set of default parameters in some type that abstracts away the calling, does supply the parameters and to the outside offers a polymorphic interface. So you'd have a std::vector<function_binder> or function_binder where function binder has a operator() that calls the function.



But when you're doing binding in the first place, you can bind it in an anonymous function, i.e. lambdas. At the time of lambda instanciation the default parameters are bound.



std::vector<void(*)()> fvec = {
{ func0(); },
{ func1(); },
{ func2(); },
}





share|improve this answer















but given that I only want to use the functions without supplying an argument




It simply doesn't work like that. Did you ever wonder, then when you're put function declarations in a header, why you have to write default parameters into the header and can not place it in the definition in the implementation source file?



That's because the default parameters are in fact not "embedded" into the function, but used by the compiler to augment a function call with those parameters at a calling location, where those parameters are omitted. (EDIT: Also, as @Aconcagua so keenly observed in a comment, since default parameters are usually defined as part of a header function declaration, any change of the default values requires a full recompilation of any compilation unit that included those headers, ergo function declarations, for the change to actually take effect!)



While it's perfectly possible to do some really weird type casting madness to construct an array of function pointers like that, eventually you'll have to cast back to the original function call signature in order to not invoke undefined behavior.



If anything you'll have to bind the function pointer, together with a set of default parameters in some type that abstracts away the calling, does supply the parameters and to the outside offers a polymorphic interface. So you'd have a std::vector<function_binder> or function_binder where function binder has a operator() that calls the function.



But when you're doing binding in the first place, you can bind it in an anonymous function, i.e. lambdas. At the time of lambda instanciation the default parameters are bound.



std::vector<void(*)()> fvec = {
{ func0(); },
{ func1(); },
{ func2(); },
}






share|improve this answer














share|improve this answer



share|improve this answer








edited Dec 5 at 12:58

























answered Dec 5 at 9:28









datenwolf

131k10129233




131k10129233












  • Might be worth to mention that, as parameters are provided in header, if changing these, any translation units relying on need to be re-compiled to make these changes effective there as well...
    – Aconcagua
    Dec 5 at 12:13










  • @Aconcagua: That's a very good point!
    – datenwolf
    Dec 5 at 12:55


















  • Might be worth to mention that, as parameters are provided in header, if changing these, any translation units relying on need to be re-compiled to make these changes effective there as well...
    – Aconcagua
    Dec 5 at 12:13










  • @Aconcagua: That's a very good point!
    – datenwolf
    Dec 5 at 12:55
















Might be worth to mention that, as parameters are provided in header, if changing these, any translation units relying on need to be re-compiled to make these changes effective there as well...
– Aconcagua
Dec 5 at 12:13




Might be worth to mention that, as parameters are provided in header, if changing these, any translation units relying on need to be re-compiled to make these changes effective there as well...
– Aconcagua
Dec 5 at 12:13












@Aconcagua: That's a very good point!
– datenwolf
Dec 5 at 12:55




@Aconcagua: That's a very good point!
– datenwolf
Dec 5 at 12:55










up vote
9
down vote













You can use std::bind



std::function<ParentClass *(void)> arr[5] = {
std::bind(&fun1),
std::bind(&fun2),
std::bind(&fun3, false),
std::bind(&fun4),
std::bind(&fun5, 1, 3)
};


now you can do



for(int i=0; i<5; i++)
arr[i]();


You have to make sure every function parameter of all functions are bound.



This also works well with member functions. You just have to bind the object reference (e.g. this) as first parameter.






share|improve this answer



















  • 1




    since C++11 and above there is no point to use bind since lambda is more handy and faster.
    – Marek R
    Dec 5 at 9:42












  • @Marek R - Depending on implementation std::bind might just return an lambda because it's return type is unspecified. It's probably just a matter of taste which one you use.
    – Detonar
    Dec 5 at 9:47






  • 2




    My taste says std::bind since if forces less disciplined developer to write small functions. Lambda is often overused and grows to ridicules sizes, but still it is easier to use and it is faster. std::bind creates complex templates which is annoying when analyzing a crash logs.
    – Marek R
    Dec 5 at 9:51












  • This does not compile.
    – Quentin
    Dec 5 at 9:55










  • @Quentin - Thanks. Of course you can't have an array of auto. I corrected that.
    – Detonar
    Dec 5 at 10:08















up vote
9
down vote













You can use std::bind



std::function<ParentClass *(void)> arr[5] = {
std::bind(&fun1),
std::bind(&fun2),
std::bind(&fun3, false),
std::bind(&fun4),
std::bind(&fun5, 1, 3)
};


now you can do



for(int i=0; i<5; i++)
arr[i]();


You have to make sure every function parameter of all functions are bound.



This also works well with member functions. You just have to bind the object reference (e.g. this) as first parameter.






share|improve this answer



















  • 1




    since C++11 and above there is no point to use bind since lambda is more handy and faster.
    – Marek R
    Dec 5 at 9:42












  • @Marek R - Depending on implementation std::bind might just return an lambda because it's return type is unspecified. It's probably just a matter of taste which one you use.
    – Detonar
    Dec 5 at 9:47






  • 2




    My taste says std::bind since if forces less disciplined developer to write small functions. Lambda is often overused and grows to ridicules sizes, but still it is easier to use and it is faster. std::bind creates complex templates which is annoying when analyzing a crash logs.
    – Marek R
    Dec 5 at 9:51












  • This does not compile.
    – Quentin
    Dec 5 at 9:55










  • @Quentin - Thanks. Of course you can't have an array of auto. I corrected that.
    – Detonar
    Dec 5 at 10:08













up vote
9
down vote










up vote
9
down vote









You can use std::bind



std::function<ParentClass *(void)> arr[5] = {
std::bind(&fun1),
std::bind(&fun2),
std::bind(&fun3, false),
std::bind(&fun4),
std::bind(&fun5, 1, 3)
};


now you can do



for(int i=0; i<5; i++)
arr[i]();


You have to make sure every function parameter of all functions are bound.



This also works well with member functions. You just have to bind the object reference (e.g. this) as first parameter.






share|improve this answer














You can use std::bind



std::function<ParentClass *(void)> arr[5] = {
std::bind(&fun1),
std::bind(&fun2),
std::bind(&fun3, false),
std::bind(&fun4),
std::bind(&fun5, 1, 3)
};


now you can do



for(int i=0; i<5; i++)
arr[i]();


You have to make sure every function parameter of all functions are bound.



This also works well with member functions. You just have to bind the object reference (e.g. this) as first parameter.







share|improve this answer














share|improve this answer



share|improve this answer








edited Dec 12 at 9:33

























answered Dec 5 at 9:27









Detonar

962111




962111








  • 1




    since C++11 and above there is no point to use bind since lambda is more handy and faster.
    – Marek R
    Dec 5 at 9:42












  • @Marek R - Depending on implementation std::bind might just return an lambda because it's return type is unspecified. It's probably just a matter of taste which one you use.
    – Detonar
    Dec 5 at 9:47






  • 2




    My taste says std::bind since if forces less disciplined developer to write small functions. Lambda is often overused and grows to ridicules sizes, but still it is easier to use and it is faster. std::bind creates complex templates which is annoying when analyzing a crash logs.
    – Marek R
    Dec 5 at 9:51












  • This does not compile.
    – Quentin
    Dec 5 at 9:55










  • @Quentin - Thanks. Of course you can't have an array of auto. I corrected that.
    – Detonar
    Dec 5 at 10:08














  • 1




    since C++11 and above there is no point to use bind since lambda is more handy and faster.
    – Marek R
    Dec 5 at 9:42












  • @Marek R - Depending on implementation std::bind might just return an lambda because it's return type is unspecified. It's probably just a matter of taste which one you use.
    – Detonar
    Dec 5 at 9:47






  • 2




    My taste says std::bind since if forces less disciplined developer to write small functions. Lambda is often overused and grows to ridicules sizes, but still it is easier to use and it is faster. std::bind creates complex templates which is annoying when analyzing a crash logs.
    – Marek R
    Dec 5 at 9:51












  • This does not compile.
    – Quentin
    Dec 5 at 9:55










  • @Quentin - Thanks. Of course you can't have an array of auto. I corrected that.
    – Detonar
    Dec 5 at 10:08








1




1




since C++11 and above there is no point to use bind since lambda is more handy and faster.
– Marek R
Dec 5 at 9:42






since C++11 and above there is no point to use bind since lambda is more handy and faster.
– Marek R
Dec 5 at 9:42














@Marek R - Depending on implementation std::bind might just return an lambda because it's return type is unspecified. It's probably just a matter of taste which one you use.
– Detonar
Dec 5 at 9:47




@Marek R - Depending on implementation std::bind might just return an lambda because it's return type is unspecified. It's probably just a matter of taste which one you use.
– Detonar
Dec 5 at 9:47




2




2




My taste says std::bind since if forces less disciplined developer to write small functions. Lambda is often overused and grows to ridicules sizes, but still it is easier to use and it is faster. std::bind creates complex templates which is annoying when analyzing a crash logs.
– Marek R
Dec 5 at 9:51






My taste says std::bind since if forces less disciplined developer to write small functions. Lambda is often overused and grows to ridicules sizes, but still it is easier to use and it is faster. std::bind creates complex templates which is annoying when analyzing a crash logs.
– Marek R
Dec 5 at 9:51














This does not compile.
– Quentin
Dec 5 at 9:55




This does not compile.
– Quentin
Dec 5 at 9:55












@Quentin - Thanks. Of course you can't have an array of auto. I corrected that.
– Detonar
Dec 5 at 10:08




@Quentin - Thanks. Of course you can't have an array of auto. I corrected that.
– Detonar
Dec 5 at 10:08










up vote
3
down vote













A c++20 solution:



#define RETURNS(...) 
noexcept(noexcept(__VA_ARGS__))
-> decltype(__VA_ARGS__)
{ return __VA_ARGS__; }


template<auto f, class R, class...Args>
struct explicit_function_caster {
using Sig=R(Args...);
using pSig=Sig*;
constexpr operator pSig()const {
return (Args...args)->R {
return static_cast<R>(f(std::forward<Args>(args)...));
};
}
};

template<auto f>
struct overload_storer_t {
template<class R, class...Args>
constexpr (*operator R() const)(Args...) const {
return explicit_function_caster<f, R, Args...>{};
}
template<class...Args>
auto operator()(Args&&...args)
RETURNS( f( std::forward<Args>(args)... ) )
};
template<auto f>
overload_storer_t<f> generate_overloads={};

#define OVERLOADS_OF(...)
generate_overloads<
(auto&&...args)
RETURNS( __VA_ARGS__( decltype(args)(args)... ) )
>


which is a lot of boilerplate, but gets us:



ParentClass* (*arr[5])() = {
OVERLOADS_OF(fun1),
OVERLOADS_OF(fun2),
OVERLOADS_OF(fun3),
OVERLOADS_OF(fun4),
OVERLOADS_OF(fun5)
};
void (*arr2[5])() = {
OVERLOADS_OF(fun1),
OVERLOADS_OF(fun2),
OVERLOADS_OF(fun3),
OVERLOADS_OF(fun4),
OVERLOADS_OF(fun5)
};


basically generate_overloads<x> takes a constexpr callable object x and lets you cast it at compile time to a pointer to a function of any compatible signature and call it with (almost) any signature.



Meanwhile, OVERLOADS_OF converts a function name into a constexpr object that does overload resolution on that function name. I use it here because fun3 as a function pointer does not know about its default arguments, but at overload resolution time it does.



In this particular case, it is far easier to just write toy lambdas to do this work; this is just an attempt to automate writing those toy lambdas for arbitrary compatible signatures.






share|improve this answer























  • constexpr (*operator R() const)(Args...) const oh what the hell... Also, is decltype(args)(args)... a replacement for std::forward or is there additional subtlety?
    – Quentin
    Dec 5 at 20:56










  • @Quentin Yes. I don't have the type of args. The cast operator was there because the C++2a compilers didn't like auto based partial specialization, so I couldn't easily unpack a Sig: that is a type-deduced conversion operator to function pointer.
    – Yakk - Adam Nevraumont
    Dec 5 at 21:06










  • I can't fathom why there are two consts in there though...
    – Quentin
    Dec 5 at 21:41






  • 1




    @Quentin Laugh, I think I converted to a const function pointer in a const method. Accidentally: the fact the function pointer is const is pointless.
    – Yakk - Adam Nevraumont
    Dec 5 at 22:04

















up vote
3
down vote













A c++20 solution:



#define RETURNS(...) 
noexcept(noexcept(__VA_ARGS__))
-> decltype(__VA_ARGS__)
{ return __VA_ARGS__; }


template<auto f, class R, class...Args>
struct explicit_function_caster {
using Sig=R(Args...);
using pSig=Sig*;
constexpr operator pSig()const {
return (Args...args)->R {
return static_cast<R>(f(std::forward<Args>(args)...));
};
}
};

template<auto f>
struct overload_storer_t {
template<class R, class...Args>
constexpr (*operator R() const)(Args...) const {
return explicit_function_caster<f, R, Args...>{};
}
template<class...Args>
auto operator()(Args&&...args)
RETURNS( f( std::forward<Args>(args)... ) )
};
template<auto f>
overload_storer_t<f> generate_overloads={};

#define OVERLOADS_OF(...)
generate_overloads<
(auto&&...args)
RETURNS( __VA_ARGS__( decltype(args)(args)... ) )
>


which is a lot of boilerplate, but gets us:



ParentClass* (*arr[5])() = {
OVERLOADS_OF(fun1),
OVERLOADS_OF(fun2),
OVERLOADS_OF(fun3),
OVERLOADS_OF(fun4),
OVERLOADS_OF(fun5)
};
void (*arr2[5])() = {
OVERLOADS_OF(fun1),
OVERLOADS_OF(fun2),
OVERLOADS_OF(fun3),
OVERLOADS_OF(fun4),
OVERLOADS_OF(fun5)
};


basically generate_overloads<x> takes a constexpr callable object x and lets you cast it at compile time to a pointer to a function of any compatible signature and call it with (almost) any signature.



Meanwhile, OVERLOADS_OF converts a function name into a constexpr object that does overload resolution on that function name. I use it here because fun3 as a function pointer does not know about its default arguments, but at overload resolution time it does.



In this particular case, it is far easier to just write toy lambdas to do this work; this is just an attempt to automate writing those toy lambdas for arbitrary compatible signatures.






share|improve this answer























  • constexpr (*operator R() const)(Args...) const oh what the hell... Also, is decltype(args)(args)... a replacement for std::forward or is there additional subtlety?
    – Quentin
    Dec 5 at 20:56










  • @Quentin Yes. I don't have the type of args. The cast operator was there because the C++2a compilers didn't like auto based partial specialization, so I couldn't easily unpack a Sig: that is a type-deduced conversion operator to function pointer.
    – Yakk - Adam Nevraumont
    Dec 5 at 21:06










  • I can't fathom why there are two consts in there though...
    – Quentin
    Dec 5 at 21:41






  • 1




    @Quentin Laugh, I think I converted to a const function pointer in a const method. Accidentally: the fact the function pointer is const is pointless.
    – Yakk - Adam Nevraumont
    Dec 5 at 22:04















up vote
3
down vote










up vote
3
down vote









A c++20 solution:



#define RETURNS(...) 
noexcept(noexcept(__VA_ARGS__))
-> decltype(__VA_ARGS__)
{ return __VA_ARGS__; }


template<auto f, class R, class...Args>
struct explicit_function_caster {
using Sig=R(Args...);
using pSig=Sig*;
constexpr operator pSig()const {
return (Args...args)->R {
return static_cast<R>(f(std::forward<Args>(args)...));
};
}
};

template<auto f>
struct overload_storer_t {
template<class R, class...Args>
constexpr (*operator R() const)(Args...) const {
return explicit_function_caster<f, R, Args...>{};
}
template<class...Args>
auto operator()(Args&&...args)
RETURNS( f( std::forward<Args>(args)... ) )
};
template<auto f>
overload_storer_t<f> generate_overloads={};

#define OVERLOADS_OF(...)
generate_overloads<
(auto&&...args)
RETURNS( __VA_ARGS__( decltype(args)(args)... ) )
>


which is a lot of boilerplate, but gets us:



ParentClass* (*arr[5])() = {
OVERLOADS_OF(fun1),
OVERLOADS_OF(fun2),
OVERLOADS_OF(fun3),
OVERLOADS_OF(fun4),
OVERLOADS_OF(fun5)
};
void (*arr2[5])() = {
OVERLOADS_OF(fun1),
OVERLOADS_OF(fun2),
OVERLOADS_OF(fun3),
OVERLOADS_OF(fun4),
OVERLOADS_OF(fun5)
};


basically generate_overloads<x> takes a constexpr callable object x and lets you cast it at compile time to a pointer to a function of any compatible signature and call it with (almost) any signature.



Meanwhile, OVERLOADS_OF converts a function name into a constexpr object that does overload resolution on that function name. I use it here because fun3 as a function pointer does not know about its default arguments, but at overload resolution time it does.



In this particular case, it is far easier to just write toy lambdas to do this work; this is just an attempt to automate writing those toy lambdas for arbitrary compatible signatures.






share|improve this answer














A c++20 solution:



#define RETURNS(...) 
noexcept(noexcept(__VA_ARGS__))
-> decltype(__VA_ARGS__)
{ return __VA_ARGS__; }


template<auto f, class R, class...Args>
struct explicit_function_caster {
using Sig=R(Args...);
using pSig=Sig*;
constexpr operator pSig()const {
return (Args...args)->R {
return static_cast<R>(f(std::forward<Args>(args)...));
};
}
};

template<auto f>
struct overload_storer_t {
template<class R, class...Args>
constexpr (*operator R() const)(Args...) const {
return explicit_function_caster<f, R, Args...>{};
}
template<class...Args>
auto operator()(Args&&...args)
RETURNS( f( std::forward<Args>(args)... ) )
};
template<auto f>
overload_storer_t<f> generate_overloads={};

#define OVERLOADS_OF(...)
generate_overloads<
(auto&&...args)
RETURNS( __VA_ARGS__( decltype(args)(args)... ) )
>


which is a lot of boilerplate, but gets us:



ParentClass* (*arr[5])() = {
OVERLOADS_OF(fun1),
OVERLOADS_OF(fun2),
OVERLOADS_OF(fun3),
OVERLOADS_OF(fun4),
OVERLOADS_OF(fun5)
};
void (*arr2[5])() = {
OVERLOADS_OF(fun1),
OVERLOADS_OF(fun2),
OVERLOADS_OF(fun3),
OVERLOADS_OF(fun4),
OVERLOADS_OF(fun5)
};


basically generate_overloads<x> takes a constexpr callable object x and lets you cast it at compile time to a pointer to a function of any compatible signature and call it with (almost) any signature.



Meanwhile, OVERLOADS_OF converts a function name into a constexpr object that does overload resolution on that function name. I use it here because fun3 as a function pointer does not know about its default arguments, but at overload resolution time it does.



In this particular case, it is far easier to just write toy lambdas to do this work; this is just an attempt to automate writing those toy lambdas for arbitrary compatible signatures.







share|improve this answer














share|improve this answer



share|improve this answer








edited Dec 6 at 14:13

























answered Dec 5 at 15:53









Yakk - Adam Nevraumont

181k19188368




181k19188368












  • constexpr (*operator R() const)(Args...) const oh what the hell... Also, is decltype(args)(args)... a replacement for std::forward or is there additional subtlety?
    – Quentin
    Dec 5 at 20:56










  • @Quentin Yes. I don't have the type of args. The cast operator was there because the C++2a compilers didn't like auto based partial specialization, so I couldn't easily unpack a Sig: that is a type-deduced conversion operator to function pointer.
    – Yakk - Adam Nevraumont
    Dec 5 at 21:06










  • I can't fathom why there are two consts in there though...
    – Quentin
    Dec 5 at 21:41






  • 1




    @Quentin Laugh, I think I converted to a const function pointer in a const method. Accidentally: the fact the function pointer is const is pointless.
    – Yakk - Adam Nevraumont
    Dec 5 at 22:04




















  • constexpr (*operator R() const)(Args...) const oh what the hell... Also, is decltype(args)(args)... a replacement for std::forward or is there additional subtlety?
    – Quentin
    Dec 5 at 20:56










  • @Quentin Yes. I don't have the type of args. The cast operator was there because the C++2a compilers didn't like auto based partial specialization, so I couldn't easily unpack a Sig: that is a type-deduced conversion operator to function pointer.
    – Yakk - Adam Nevraumont
    Dec 5 at 21:06










  • I can't fathom why there are two consts in there though...
    – Quentin
    Dec 5 at 21:41






  • 1




    @Quentin Laugh, I think I converted to a const function pointer in a const method. Accidentally: the fact the function pointer is const is pointless.
    – Yakk - Adam Nevraumont
    Dec 5 at 22:04


















constexpr (*operator R() const)(Args...) const oh what the hell... Also, is decltype(args)(args)... a replacement for std::forward or is there additional subtlety?
– Quentin
Dec 5 at 20:56




constexpr (*operator R() const)(Args...) const oh what the hell... Also, is decltype(args)(args)... a replacement for std::forward or is there additional subtlety?
– Quentin
Dec 5 at 20:56












@Quentin Yes. I don't have the type of args. The cast operator was there because the C++2a compilers didn't like auto based partial specialization, so I couldn't easily unpack a Sig: that is a type-deduced conversion operator to function pointer.
– Yakk - Adam Nevraumont
Dec 5 at 21:06




@Quentin Yes. I don't have the type of args. The cast operator was there because the C++2a compilers didn't like auto based partial specialization, so I couldn't easily unpack a Sig: that is a type-deduced conversion operator to function pointer.
– Yakk - Adam Nevraumont
Dec 5 at 21:06












I can't fathom why there are two consts in there though...
– Quentin
Dec 5 at 21:41




I can't fathom why there are two consts in there though...
– Quentin
Dec 5 at 21:41




1




1




@Quentin Laugh, I think I converted to a const function pointer in a const method. Accidentally: the fact the function pointer is const is pointless.
– Yakk - Adam Nevraumont
Dec 5 at 22:04






@Quentin Laugh, I think I converted to a const function pointer in a const method. Accidentally: the fact the function pointer is const is pointless.
– Yakk - Adam Nevraumont
Dec 5 at 22:04












up vote
1
down vote













Since you have tagged question with C++14 you should not use function pointers!



With C++14 you should prefer std::function and lambadas.



Also you should not use C style array, but only std::array and/or std::vector.



Also avoid raw pointers, use std::unique_ptr and std::shared_ptr.



So simplest and best whay to solve it is:



std::array<std::function<ParentClass*()>,5> arr {
() { return fun1(); },
() { return fun2(); },
() { return fun3(true); },
() { return fun4(); },
() { return fun5(7, 9); }
};


Why not simple array of pointers like in @Quentin answer? He used lambdas, but he can't use lambda which binds anything (if you need to).






share|improve this answer



















  • 2




    Downvoted because std::function is a heavyweight facility, and the problem at hand does not require any of the functionality it provides over plain function pointers.
    – Quentin
    Dec 5 at 9:54






  • 7




    I'm tempted to give an upvote for "Lambadas" :)
    – Willem van Rumpt
    Dec 5 at 10:08















up vote
1
down vote













Since you have tagged question with C++14 you should not use function pointers!



With C++14 you should prefer std::function and lambadas.



Also you should not use C style array, but only std::array and/or std::vector.



Also avoid raw pointers, use std::unique_ptr and std::shared_ptr.



So simplest and best whay to solve it is:



std::array<std::function<ParentClass*()>,5> arr {
() { return fun1(); },
() { return fun2(); },
() { return fun3(true); },
() { return fun4(); },
() { return fun5(7, 9); }
};


Why not simple array of pointers like in @Quentin answer? He used lambdas, but he can't use lambda which binds anything (if you need to).






share|improve this answer



















  • 2




    Downvoted because std::function is a heavyweight facility, and the problem at hand does not require any of the functionality it provides over plain function pointers.
    – Quentin
    Dec 5 at 9:54






  • 7




    I'm tempted to give an upvote for "Lambadas" :)
    – Willem van Rumpt
    Dec 5 at 10:08













up vote
1
down vote










up vote
1
down vote









Since you have tagged question with C++14 you should not use function pointers!



With C++14 you should prefer std::function and lambadas.



Also you should not use C style array, but only std::array and/or std::vector.



Also avoid raw pointers, use std::unique_ptr and std::shared_ptr.



So simplest and best whay to solve it is:



std::array<std::function<ParentClass*()>,5> arr {
() { return fun1(); },
() { return fun2(); },
() { return fun3(true); },
() { return fun4(); },
() { return fun5(7, 9); }
};


Why not simple array of pointers like in @Quentin answer? He used lambdas, but he can't use lambda which binds anything (if you need to).






share|improve this answer














Since you have tagged question with C++14 you should not use function pointers!



With C++14 you should prefer std::function and lambadas.



Also you should not use C style array, but only std::array and/or std::vector.



Also avoid raw pointers, use std::unique_ptr and std::shared_ptr.



So simplest and best whay to solve it is:



std::array<std::function<ParentClass*()>,5> arr {
() { return fun1(); },
() { return fun2(); },
() { return fun3(true); },
() { return fun4(); },
() { return fun5(7, 9); }
};


Why not simple array of pointers like in @Quentin answer? He used lambdas, but he can't use lambda which binds anything (if you need to).







share|improve this answer














share|improve this answer



share|improve this answer








edited Dec 6 at 22:34









Remy Lebeau

330k18248438




330k18248438










answered Dec 5 at 9:34









Marek R

12.6k22671




12.6k22671








  • 2




    Downvoted because std::function is a heavyweight facility, and the problem at hand does not require any of the functionality it provides over plain function pointers.
    – Quentin
    Dec 5 at 9:54






  • 7




    I'm tempted to give an upvote for "Lambadas" :)
    – Willem van Rumpt
    Dec 5 at 10:08














  • 2




    Downvoted because std::function is a heavyweight facility, and the problem at hand does not require any of the functionality it provides over plain function pointers.
    – Quentin
    Dec 5 at 9:54






  • 7




    I'm tempted to give an upvote for "Lambadas" :)
    – Willem van Rumpt
    Dec 5 at 10:08








2




2




Downvoted because std::function is a heavyweight facility, and the problem at hand does not require any of the functionality it provides over plain function pointers.
– Quentin
Dec 5 at 9:54




Downvoted because std::function is a heavyweight facility, and the problem at hand does not require any of the functionality it provides over plain function pointers.
– Quentin
Dec 5 at 9:54




7




7




I'm tempted to give an upvote for "Lambadas" :)
– Willem van Rumpt
Dec 5 at 10:08




I'm tempted to give an upvote for "Lambadas" :)
– Willem van Rumpt
Dec 5 at 10:08


















draft saved

draft discarded




















































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.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • 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.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53628791%2fhow-do-i-create-an-array-of-function-pointers-of-different-prototypes%23new-answer', 'question_page');
}
);

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







Popular posts from this blog

flock() on closed filehandle LOCK_FILE at /usr/bin/apt-mirror

Mangá

Eduardo VII do Reino Unido