How Can I Pass an Undefined Method Like an Undefined Function
Asked Answered
S

1

1

Given that I was passing the undefined function:

void foo(char, short);

I learned how to obtain the type tuple of the arguments by calling decltype(m(foo)) with this function:

template <typename Ret, typename... Args>
tuple<Args...> m(Ret(Args...));

I would now like to pass an undefined method:

struct bar { void foo(char, short); };

I had tried rewriting m like:

template <typename Ret, typename C, typename... Args>
tuple<Args...> m(Ret(C::*)(Args...));

But when I try to call this similarly with decltype(m(bar::foo)) I get the error:

invalid use of non-static member function void bar::foo(char, short int)

How can I pass this method like I did for the function?

Subdelirium answered 20/7, 2016 at 13:33 Comment(2)
Remember that a non-static member function pointer needs an instance of its class (an object) on which to operate. One way of passing member function pointer(s) with an object is with std::function. See the print_add example: en.cppreference.com/w/cpp/utility/functional/functionVerda
@RichardCritten Note the "undefined function" and "undefined method" function objects will not work, they need an address. Frankly I'm not even sure how decltype(m(foo)) works, I'm just kinda going with it.Subdelirium
S
2

If you only want to use decltype on it, you simply need an extra &:

decltype(m(&bar::foo))
Simla answered 20/7, 2016 at 13:54 Comment(7)
Note the "undefined method" I can't take the address. I'll bold those in the question so it's clear why this isn't a solution. It's almost like the function was treated as an expression when I passed it. Not sure how to do something similar with a method.Subdelirium
@JonathanMee Why do you mean by "undefined method"? A method that is declared but not define? If so, the above code work perfectly. The expression you give to decltype is never evaluated.Simla
"The above code work perfectly"[sic] I'm guessing you didn't test it before you made that statement: https://mcmap.net/q/665145/-should-taking-the-address-of-a-templatized-function-trigger-its-compilation/2642059 It will not work at all.Subdelirium
@JonathanMee I did test it, you did not. There is a huge difference between your code and the link you provide: In your code, the & is inside the decltype. Per the standard The operand of the decltype specifier is an unevaluated operand and An expression is potentially evaluated unless it is an unevaluated operand (Clause 5) or a subexpression thereof, so no, &bar::foo will never be evaluated in the above context.Simla
Wow... so taking the address doesn't evaluate even though taking the address requires the function to be defined...Subdelirium
@JonathanMee That's because decltype doesn't look at the implementation of functions, only the return types. It knows the expression &bar::foo returns a method pointer, it doesn't need to know if it actually works.Graven
@JonathanMee This is exactly the same behavior as in this question you asked a few days ago - Whatever is inside decltype() will never be evaluated, so you will never really "take the address of the function". All the compilers needs to know is that &bar::foo is of type void (bar::*) (char, short);, which it gets from the declaration, from this it deduces which overloads of m it needs to consider, and from this it can get the return types.Simla

© 2022 - 2024 — McMap. All rights reserved.