0

I'm trying to extend to methods the technique explained here for functions. The problem is the method signature template parameter. For instance, a wrapper for the sin function is created this way:

template<typename Sig, Sig& S> struct wrapper;

template<typename Ret, typename... Args, Ret(&P)(Args...)>
struct wrapper<Ret(Args...), P> {
    // blah
}

and then is instantiated with

wrapper<decltype(sin), sin>

But for a method bool Foo::blah(int) this technique is rejected:

template<class C, typename Sig, Sig& S> struct wrapper;

template<class C, typename Ret, typename... Args, Ret(C::*P)(Args...)>
struct wrapper<Ret(C::)(Args...), P> {
    // blah
}

wrapper<decltype(Foo::blah), &Foo::blah>

So what's the proper syntax?

Community
  • 1
  • 1
user643005
  • 365
  • 2
  • 9
  • 1
    Note that term "method" isn't well-defined in C++ context; you might consider switching to standard term "member function". – Griwes Jan 13 '13 at 12:27

1 Answers1

2

There is no analogue of free function types for member functions. You need to work with the pointers-to-member-functions directly.

Try something like this:

template <typename C, typename MFP, MFP> struct wrapper;

template <typename C, typename R, typename ...Args, R (C::*MFP)(Args...)>
struct wrapper<C, R (C::*)(Args...), MFP>
{
    // ...
};

Note that this will get a bit verbose if you want to admit all the possible combinations of CV- and rvalue-qualifications.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • I know this does compile (I tried it out myself), but isn't it forbidden by §14.1/15? *"A template parameter pack that is a pack expansion shall not expand a parameter pack declared in the same template-parameter-list"*. I realize this is in the context of a template specialization, but nothing seems to mention this particular concept as an exception to that rule. Am I missing something? – Andy Prowl Jan 13 '13 at 13:51
  • Oh, I see: `Args...` is not a "template parameter pack". My bad, please forget – Andy Prowl Jan 13 '13 at 13:56
  • Thanks! But I'm curious about your comment about _"all the possible CV- and rvalue-quualifications"_ I know I have to specialize for const and non-const member-functions, but what about rvalue-qualifications? – user643005 Jan 13 '13 at 18:33
  • To clarify my comment above: If you are talking about the guts of the wrapper, that's a different issue, this one is about the machinery that captures the member-function, not the part that actually uses it. Admittedly, I'm not completely up to date with the new standard, so maybe I'm missing something. – user643005 Jan 13 '13 at 18:47
  • @user643005: You have things like `R C::f() const` and `R C::f() volatile &&` etc. I think there are eight variants all in all. – Kerrek SB Jan 13 '13 at 19:18
  • Thanks. I've never seen a volatile member-function, so that case (and `const volatile`) will remain unsupported :-) – user643005 Jan 13 '13 at 19:38
  • technically the type of a member function is an ordinary function type. nothing special. there is no special "free" function type either. the problem is not the type of a member function, but trying to refer to it without calling it directly or directly taking its address. – Johannes Schaub - litb Jan 13 '13 at 20:29
  • @JohannesSchaub-litb: Well, but there isn't a member function reference type, either... can you typedef the naked function type and then make that a pointer? – Kerrek SB Jan 13 '13 at 20:35
  • @KerrekSB by saying "there isn't a member function reference type", i suppose you suppose that there is a "member function type" that is not a plain ordinary function type. but there is no such special type, so there can be no special "member function reference type" that is not a plain ordinary function reference type either. – Johannes Schaub - litb Jan 13 '13 at 20:59
  • "can you typedef the naked fuction type and then make that a pointer?". Yes, see: "typedef int foo(); struct A { foo f; foo *fr; };` this code is valid and compiles. A contains one member function and one data member, the type of which is the requested pointer. – Johannes Schaub - litb Jan 13 '13 at 21:00
  • The thing you keep in mind is: The type of a member function is not a useful notion to talk about. The only time it breaks out into the language is when you form a member pointer: The type of the member (function) then is nested in the type of the member pointer type `F C::*`. The `F` is the function type of the (member) function. When you refer to a member function in an object expression `obj.memberFunction` that expression actually has a function type and is an rvalue. However, all you can do is applying the function call operator. So it is not really a useful thing to talk about. – Johannes Schaub - litb Jan 13 '13 at 21:06
  • @JohannesSchaub-litb: I was thinking more along the lines of this: `struct A { int f(bool, char); }; typedef int (A::mf)(bool, char);`. Does that exist? Then I could say `mf * p = &A::f;`. – Kerrek SB Jan 13 '13 at 21:09
  • @KerrekSB no, that doesn't work. It would be an out of class declaration of a member. If you were allowed to redeclare typedefs using a qualified name, this would be a valid code that contains it: `struct A { typedef int mf(bool, char); }; typedef int (A::mf)(bool, char); ` – Johannes Schaub - litb Jan 13 '13 at 21:19