How to check method signature in runtime










3















Is there any way to determine at runtime the type of method's argument in C++03? I am thinking about such way:



#include <cstdio>

template<class T, class U>
struct is_same
static const bool result = false;
;

template<class T>
struct is_same<T, T>
static const bool result = true;
;

template<class ToFind, class Ret, class T, class Arg>
bool hasArg1(ToFind, Ret (T::*)(Arg))return is_same<ToFind, Arg>::result;

template<class ToFind, class Ret, class T, class Arg1, class Arg2>
bool hasArg1(ToFind, Ret (T::*)(Arg1, Arg2))return is_same<ToFind, Arg1>::result;

struct A

int fun1(int a)return a+1;
;

int main()
std::printf("int arg1: %sn", hasArg1(1, &A::fun1) ? "yes" : "no");



but I want something like this:



hasArg1<int>(&A::fun1)


instead of



hasArg1(1, &A::fun1)









share|improve this question



















  • 2





    Run time is too late. You can determine either at compile time or not at all.

    – n.m.
    Nov 14 '18 at 7:39















3















Is there any way to determine at runtime the type of method's argument in C++03? I am thinking about such way:



#include <cstdio>

template<class T, class U>
struct is_same
static const bool result = false;
;

template<class T>
struct is_same<T, T>
static const bool result = true;
;

template<class ToFind, class Ret, class T, class Arg>
bool hasArg1(ToFind, Ret (T::*)(Arg))return is_same<ToFind, Arg>::result;

template<class ToFind, class Ret, class T, class Arg1, class Arg2>
bool hasArg1(ToFind, Ret (T::*)(Arg1, Arg2))return is_same<ToFind, Arg1>::result;

struct A

int fun1(int a)return a+1;
;

int main()
std::printf("int arg1: %sn", hasArg1(1, &A::fun1) ? "yes" : "no");



but I want something like this:



hasArg1<int>(&A::fun1)


instead of



hasArg1(1, &A::fun1)









share|improve this question



















  • 2





    Run time is too late. You can determine either at compile time or not at all.

    – n.m.
    Nov 14 '18 at 7:39













3












3








3


1






Is there any way to determine at runtime the type of method's argument in C++03? I am thinking about such way:



#include <cstdio>

template<class T, class U>
struct is_same
static const bool result = false;
;

template<class T>
struct is_same<T, T>
static const bool result = true;
;

template<class ToFind, class Ret, class T, class Arg>
bool hasArg1(ToFind, Ret (T::*)(Arg))return is_same<ToFind, Arg>::result;

template<class ToFind, class Ret, class T, class Arg1, class Arg2>
bool hasArg1(ToFind, Ret (T::*)(Arg1, Arg2))return is_same<ToFind, Arg1>::result;

struct A

int fun1(int a)return a+1;
;

int main()
std::printf("int arg1: %sn", hasArg1(1, &A::fun1) ? "yes" : "no");



but I want something like this:



hasArg1<int>(&A::fun1)


instead of



hasArg1(1, &A::fun1)









share|improve this question
















Is there any way to determine at runtime the type of method's argument in C++03? I am thinking about such way:



#include <cstdio>

template<class T, class U>
struct is_same
static const bool result = false;
;

template<class T>
struct is_same<T, T>
static const bool result = true;
;

template<class ToFind, class Ret, class T, class Arg>
bool hasArg1(ToFind, Ret (T::*)(Arg))return is_same<ToFind, Arg>::result;

template<class ToFind, class Ret, class T, class Arg1, class Arg2>
bool hasArg1(ToFind, Ret (T::*)(Arg1, Arg2))return is_same<ToFind, Arg1>::result;

struct A

int fun1(int a)return a+1;
;

int main()
std::printf("int arg1: %sn", hasArg1(1, &A::fun1) ? "yes" : "no");



but I want something like this:



hasArg1<int>(&A::fun1)


instead of



hasArg1(1, &A::fun1)






c++ c++03






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 14 '18 at 7:37









StoryTeller

100k12204272




100k12204272










asked Nov 14 '18 at 6:58









max bushlyamax bushlya

285




285







  • 2





    Run time is too late. You can determine either at compile time or not at all.

    – n.m.
    Nov 14 '18 at 7:39












  • 2





    Run time is too late. You can determine either at compile time or not at all.

    – n.m.
    Nov 14 '18 at 7:39







2




2





Run time is too late. You can determine either at compile time or not at all.

– n.m.
Nov 14 '18 at 7:39





Run time is too late. You can determine either at compile time or not at all.

– n.m.
Nov 14 '18 at 7:39












1 Answer
1






active

oldest

votes


















4














Just remove the first function argument:



template<class ToFind, class Ret, class T, class Arg>
bool hasArg1(Ret (T::*)(Arg))return is_same<ToFind, Arg>::result;

template<class ToFind, class Ret, class T, class Arg1, class Arg2>
bool hasArg1(Ret (T::*)(Arg1, Arg2))return is_same<ToFind, Arg1>::result;


Now hasArg1<int>(&A::fun1) works as you want it to.



See it Live



But bear in mind that this approach won't work if A::fun1 is overloaded.




Now, as was noted under your question. Runtime checking of such things is less useful. Usually you want that information at compile time, to affect code generation and possibly optimize based upon. c++03 is limited in its compile time capabilities compared to later revisions, but it's not impossible to make this check at compile time. Here is how you'd modify your code to do it:



template<bool C, typename T = void>
struct enable_if;

template<typename T>
struct enable_if<true, T> typedef T type; ;

template<int s> struct tag char _[s]; ;

template<class ToFind>
tag<1> hasArg1(...);

template<class ToFind, class Ret, class T, class Arg>
tag<2> hasArg1(Ret (T::*)(Arg), enable_if<is_same<ToFind, Arg>::result, void>* = 0);

// Add hasArg1 overloads to support members with more arguments

#define HAS_ARG1(ToFind, member) (sizeof(hasArg1<ToFind>(member)) != sizeof(tag<1>))


First we add a "fallback" overload that returns a type with an expected size. Then we add another overload, modified from your own. The check is relegated to another function argument. When the checks fails during overload resolution, the argument is ill-formed and substitution fails, leaving us only with the fallback, because SFINAE is awesome!



If the check passes, the second overload is well-formed and a better match, because ellipsis have the lowest priority among conversion sequences in overload resolution.



The macro is added for syntactic sugar, since the subsequent details are tedious to type over and over. We do overload resolution inside the sizeof operator. The overload chosen, via its return type, will be reflected in what sizeof(hasArg1<ToFind>(member)) reports. So we can check it against sizeof(tag<1>) (the fallback). And since sizeof is a compile time operator, we have a compile time constant that tells us if the first argument of member is ToFind.



And to prove that it is a compile time constant, we can instantiate



tag<HAS_ARG1(int, &A::fun1)> test_compile_time;


Like we do here, in GCC 4.1.2 in C++98 mode.






share|improve this answer

























  • It is something about magic!)) I have tryed the same, but there were compiler errors. After you wrote the code works fine:) Thank you. Believe my code can help anyone

    – max bushlya
    Nov 14 '18 at 8:02











  • @maxbushlya - If you think that's magic, see my edit :)

    – StoryTeller
    Nov 14 '18 at 8:04











  • One more question: how to specify the method for this approach if method is overloaded?

    – max bushlya
    Nov 14 '18 at 11:17











  • @maxbushlya - You can't. Overliading or templating means no deduction is possible. You'd need to start specifying types explicitly, which defeats the purpose doesn't it?

    – StoryTeller
    Nov 14 '18 at 11:20











  • yes, it is :(...

    – max bushlya
    Nov 14 '18 at 13:00










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
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53294670%2fhow-to-check-method-signature-in-runtime%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









4














Just remove the first function argument:



template<class ToFind, class Ret, class T, class Arg>
bool hasArg1(Ret (T::*)(Arg))return is_same<ToFind, Arg>::result;

template<class ToFind, class Ret, class T, class Arg1, class Arg2>
bool hasArg1(Ret (T::*)(Arg1, Arg2))return is_same<ToFind, Arg1>::result;


Now hasArg1<int>(&A::fun1) works as you want it to.



See it Live



But bear in mind that this approach won't work if A::fun1 is overloaded.




Now, as was noted under your question. Runtime checking of such things is less useful. Usually you want that information at compile time, to affect code generation and possibly optimize based upon. c++03 is limited in its compile time capabilities compared to later revisions, but it's not impossible to make this check at compile time. Here is how you'd modify your code to do it:



template<bool C, typename T = void>
struct enable_if;

template<typename T>
struct enable_if<true, T> typedef T type; ;

template<int s> struct tag char _[s]; ;

template<class ToFind>
tag<1> hasArg1(...);

template<class ToFind, class Ret, class T, class Arg>
tag<2> hasArg1(Ret (T::*)(Arg), enable_if<is_same<ToFind, Arg>::result, void>* = 0);

// Add hasArg1 overloads to support members with more arguments

#define HAS_ARG1(ToFind, member) (sizeof(hasArg1<ToFind>(member)) != sizeof(tag<1>))


First we add a "fallback" overload that returns a type with an expected size. Then we add another overload, modified from your own. The check is relegated to another function argument. When the checks fails during overload resolution, the argument is ill-formed and substitution fails, leaving us only with the fallback, because SFINAE is awesome!



If the check passes, the second overload is well-formed and a better match, because ellipsis have the lowest priority among conversion sequences in overload resolution.



The macro is added for syntactic sugar, since the subsequent details are tedious to type over and over. We do overload resolution inside the sizeof operator. The overload chosen, via its return type, will be reflected in what sizeof(hasArg1<ToFind>(member)) reports. So we can check it against sizeof(tag<1>) (the fallback). And since sizeof is a compile time operator, we have a compile time constant that tells us if the first argument of member is ToFind.



And to prove that it is a compile time constant, we can instantiate



tag<HAS_ARG1(int, &A::fun1)> test_compile_time;


Like we do here, in GCC 4.1.2 in C++98 mode.






share|improve this answer

























  • It is something about magic!)) I have tryed the same, but there were compiler errors. After you wrote the code works fine:) Thank you. Believe my code can help anyone

    – max bushlya
    Nov 14 '18 at 8:02











  • @maxbushlya - If you think that's magic, see my edit :)

    – StoryTeller
    Nov 14 '18 at 8:04











  • One more question: how to specify the method for this approach if method is overloaded?

    – max bushlya
    Nov 14 '18 at 11:17











  • @maxbushlya - You can't. Overliading or templating means no deduction is possible. You'd need to start specifying types explicitly, which defeats the purpose doesn't it?

    – StoryTeller
    Nov 14 '18 at 11:20











  • yes, it is :(...

    – max bushlya
    Nov 14 '18 at 13:00















4














Just remove the first function argument:



template<class ToFind, class Ret, class T, class Arg>
bool hasArg1(Ret (T::*)(Arg))return is_same<ToFind, Arg>::result;

template<class ToFind, class Ret, class T, class Arg1, class Arg2>
bool hasArg1(Ret (T::*)(Arg1, Arg2))return is_same<ToFind, Arg1>::result;


Now hasArg1<int>(&A::fun1) works as you want it to.



See it Live



But bear in mind that this approach won't work if A::fun1 is overloaded.




Now, as was noted under your question. Runtime checking of such things is less useful. Usually you want that information at compile time, to affect code generation and possibly optimize based upon. c++03 is limited in its compile time capabilities compared to later revisions, but it's not impossible to make this check at compile time. Here is how you'd modify your code to do it:



template<bool C, typename T = void>
struct enable_if;

template<typename T>
struct enable_if<true, T> typedef T type; ;

template<int s> struct tag char _[s]; ;

template<class ToFind>
tag<1> hasArg1(...);

template<class ToFind, class Ret, class T, class Arg>
tag<2> hasArg1(Ret (T::*)(Arg), enable_if<is_same<ToFind, Arg>::result, void>* = 0);

// Add hasArg1 overloads to support members with more arguments

#define HAS_ARG1(ToFind, member) (sizeof(hasArg1<ToFind>(member)) != sizeof(tag<1>))


First we add a "fallback" overload that returns a type with an expected size. Then we add another overload, modified from your own. The check is relegated to another function argument. When the checks fails during overload resolution, the argument is ill-formed and substitution fails, leaving us only with the fallback, because SFINAE is awesome!



If the check passes, the second overload is well-formed and a better match, because ellipsis have the lowest priority among conversion sequences in overload resolution.



The macro is added for syntactic sugar, since the subsequent details are tedious to type over and over. We do overload resolution inside the sizeof operator. The overload chosen, via its return type, will be reflected in what sizeof(hasArg1<ToFind>(member)) reports. So we can check it against sizeof(tag<1>) (the fallback). And since sizeof is a compile time operator, we have a compile time constant that tells us if the first argument of member is ToFind.



And to prove that it is a compile time constant, we can instantiate



tag<HAS_ARG1(int, &A::fun1)> test_compile_time;


Like we do here, in GCC 4.1.2 in C++98 mode.






share|improve this answer

























  • It is something about magic!)) I have tryed the same, but there were compiler errors. After you wrote the code works fine:) Thank you. Believe my code can help anyone

    – max bushlya
    Nov 14 '18 at 8:02











  • @maxbushlya - If you think that's magic, see my edit :)

    – StoryTeller
    Nov 14 '18 at 8:04











  • One more question: how to specify the method for this approach if method is overloaded?

    – max bushlya
    Nov 14 '18 at 11:17











  • @maxbushlya - You can't. Overliading or templating means no deduction is possible. You'd need to start specifying types explicitly, which defeats the purpose doesn't it?

    – StoryTeller
    Nov 14 '18 at 11:20











  • yes, it is :(...

    – max bushlya
    Nov 14 '18 at 13:00













4












4








4







Just remove the first function argument:



template<class ToFind, class Ret, class T, class Arg>
bool hasArg1(Ret (T::*)(Arg))return is_same<ToFind, Arg>::result;

template<class ToFind, class Ret, class T, class Arg1, class Arg2>
bool hasArg1(Ret (T::*)(Arg1, Arg2))return is_same<ToFind, Arg1>::result;


Now hasArg1<int>(&A::fun1) works as you want it to.



See it Live



But bear in mind that this approach won't work if A::fun1 is overloaded.




Now, as was noted under your question. Runtime checking of such things is less useful. Usually you want that information at compile time, to affect code generation and possibly optimize based upon. c++03 is limited in its compile time capabilities compared to later revisions, but it's not impossible to make this check at compile time. Here is how you'd modify your code to do it:



template<bool C, typename T = void>
struct enable_if;

template<typename T>
struct enable_if<true, T> typedef T type; ;

template<int s> struct tag char _[s]; ;

template<class ToFind>
tag<1> hasArg1(...);

template<class ToFind, class Ret, class T, class Arg>
tag<2> hasArg1(Ret (T::*)(Arg), enable_if<is_same<ToFind, Arg>::result, void>* = 0);

// Add hasArg1 overloads to support members with more arguments

#define HAS_ARG1(ToFind, member) (sizeof(hasArg1<ToFind>(member)) != sizeof(tag<1>))


First we add a "fallback" overload that returns a type with an expected size. Then we add another overload, modified from your own. The check is relegated to another function argument. When the checks fails during overload resolution, the argument is ill-formed and substitution fails, leaving us only with the fallback, because SFINAE is awesome!



If the check passes, the second overload is well-formed and a better match, because ellipsis have the lowest priority among conversion sequences in overload resolution.



The macro is added for syntactic sugar, since the subsequent details are tedious to type over and over. We do overload resolution inside the sizeof operator. The overload chosen, via its return type, will be reflected in what sizeof(hasArg1<ToFind>(member)) reports. So we can check it against sizeof(tag<1>) (the fallback). And since sizeof is a compile time operator, we have a compile time constant that tells us if the first argument of member is ToFind.



And to prove that it is a compile time constant, we can instantiate



tag<HAS_ARG1(int, &A::fun1)> test_compile_time;


Like we do here, in GCC 4.1.2 in C++98 mode.






share|improve this answer















Just remove the first function argument:



template<class ToFind, class Ret, class T, class Arg>
bool hasArg1(Ret (T::*)(Arg))return is_same<ToFind, Arg>::result;

template<class ToFind, class Ret, class T, class Arg1, class Arg2>
bool hasArg1(Ret (T::*)(Arg1, Arg2))return is_same<ToFind, Arg1>::result;


Now hasArg1<int>(&A::fun1) works as you want it to.



See it Live



But bear in mind that this approach won't work if A::fun1 is overloaded.




Now, as was noted under your question. Runtime checking of such things is less useful. Usually you want that information at compile time, to affect code generation and possibly optimize based upon. c++03 is limited in its compile time capabilities compared to later revisions, but it's not impossible to make this check at compile time. Here is how you'd modify your code to do it:



template<bool C, typename T = void>
struct enable_if;

template<typename T>
struct enable_if<true, T> typedef T type; ;

template<int s> struct tag char _[s]; ;

template<class ToFind>
tag<1> hasArg1(...);

template<class ToFind, class Ret, class T, class Arg>
tag<2> hasArg1(Ret (T::*)(Arg), enable_if<is_same<ToFind, Arg>::result, void>* = 0);

// Add hasArg1 overloads to support members with more arguments

#define HAS_ARG1(ToFind, member) (sizeof(hasArg1<ToFind>(member)) != sizeof(tag<1>))


First we add a "fallback" overload that returns a type with an expected size. Then we add another overload, modified from your own. The check is relegated to another function argument. When the checks fails during overload resolution, the argument is ill-formed and substitution fails, leaving us only with the fallback, because SFINAE is awesome!



If the check passes, the second overload is well-formed and a better match, because ellipsis have the lowest priority among conversion sequences in overload resolution.



The macro is added for syntactic sugar, since the subsequent details are tedious to type over and over. We do overload resolution inside the sizeof operator. The overload chosen, via its return type, will be reflected in what sizeof(hasArg1<ToFind>(member)) reports. So we can check it against sizeof(tag<1>) (the fallback). And since sizeof is a compile time operator, we have a compile time constant that tells us if the first argument of member is ToFind.



And to prove that it is a compile time constant, we can instantiate



tag<HAS_ARG1(int, &A::fun1)> test_compile_time;


Like we do here, in GCC 4.1.2 in C++98 mode.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 14 '18 at 8:04

























answered Nov 14 '18 at 7:25









StoryTellerStoryTeller

100k12204272




100k12204272












  • It is something about magic!)) I have tryed the same, but there were compiler errors. After you wrote the code works fine:) Thank you. Believe my code can help anyone

    – max bushlya
    Nov 14 '18 at 8:02











  • @maxbushlya - If you think that's magic, see my edit :)

    – StoryTeller
    Nov 14 '18 at 8:04











  • One more question: how to specify the method for this approach if method is overloaded?

    – max bushlya
    Nov 14 '18 at 11:17











  • @maxbushlya - You can't. Overliading or templating means no deduction is possible. You'd need to start specifying types explicitly, which defeats the purpose doesn't it?

    – StoryTeller
    Nov 14 '18 at 11:20











  • yes, it is :(...

    – max bushlya
    Nov 14 '18 at 13:00

















  • It is something about magic!)) I have tryed the same, but there were compiler errors. After you wrote the code works fine:) Thank you. Believe my code can help anyone

    – max bushlya
    Nov 14 '18 at 8:02











  • @maxbushlya - If you think that's magic, see my edit :)

    – StoryTeller
    Nov 14 '18 at 8:04











  • One more question: how to specify the method for this approach if method is overloaded?

    – max bushlya
    Nov 14 '18 at 11:17











  • @maxbushlya - You can't. Overliading or templating means no deduction is possible. You'd need to start specifying types explicitly, which defeats the purpose doesn't it?

    – StoryTeller
    Nov 14 '18 at 11:20











  • yes, it is :(...

    – max bushlya
    Nov 14 '18 at 13:00
















It is something about magic!)) I have tryed the same, but there were compiler errors. After you wrote the code works fine:) Thank you. Believe my code can help anyone

– max bushlya
Nov 14 '18 at 8:02





It is something about magic!)) I have tryed the same, but there were compiler errors. After you wrote the code works fine:) Thank you. Believe my code can help anyone

– max bushlya
Nov 14 '18 at 8:02













@maxbushlya - If you think that's magic, see my edit :)

– StoryTeller
Nov 14 '18 at 8:04





@maxbushlya - If you think that's magic, see my edit :)

– StoryTeller
Nov 14 '18 at 8:04













One more question: how to specify the method for this approach if method is overloaded?

– max bushlya
Nov 14 '18 at 11:17





One more question: how to specify the method for this approach if method is overloaded?

– max bushlya
Nov 14 '18 at 11:17













@maxbushlya - You can't. Overliading or templating means no deduction is possible. You'd need to start specifying types explicitly, which defeats the purpose doesn't it?

– StoryTeller
Nov 14 '18 at 11:20





@maxbushlya - You can't. Overliading or templating means no deduction is possible. You'd need to start specifying types explicitly, which defeats the purpose doesn't it?

– StoryTeller
Nov 14 '18 at 11:20













yes, it is :(...

– max bushlya
Nov 14 '18 at 13:00





yes, it is :(...

– max bushlya
Nov 14 '18 at 13:00



















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.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53294670%2fhow-to-check-method-signature-in-runtime%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

How to how show current date and time by default on contact form 7 in WordPress without taking input from user in datetimepicker

Syphilis

Darth Vader #20