4

I understand how to declare the type of a function:

typedef void (typedef_void_f)(); // typedef_void_f is void()
using alias_void_f     = void(); // alias_void_f is void()

And it can be used to declare function pointers:

void function() { std::cout << __PRETTY_FUNCTION__ << '\n'; }

typedef_void_f *a = function; // pointer to void()
alias_void_f   *b = function; // pointer to void()

For member function pointers the syntax is slightly more complicated:

struct S { void function() { std::cout << __PRETTY_FUNCTION__ << '\n'; } };

typedef void (S::*typedef_void_m_f)();
using  alias_void_m_f = void (S::*)();

typedef_void_m_f c = &S::function; // pointer to S void() member function
alias_void_m_f   d = &S::function; // pointer to S void() member function

This is my understanding of function pointers in C++ and I thought that it was enough.

But in the p0172r0 technical paper I've found a syntax that I'm not familiar:

struct host {
   int function() const;
};

template <typename TYPE>
constexpr bool test(TYPE host::*) { // <---- What is this??
    return is_same_v<TYPE, int() const>;
}

constexpr auto member = &host::function;

test(member);

As I understand the code, the test function splits the type of the function from the type of the object where the function belongs, so in the template test function the TYPE template parameter would be void() but if I try the following:

void my_test(void() S::*) {}

my_test(&S::function);

I get a bunch of syntax errors:

error: variable or field 'my_test' declared void
 void my_test(void() S::*) {}
                   ^
error: expected ')' before 'S'
 void my_test(void() S::*) {}
                     ^
error: 'my_test' was not declared in this scope
     my_test(&S::function);

So is obvious that I'm not understanding the p0172r0's test function syntax.

Can someone explain the details of the template <typename TYPE> constexpr bool test(TYPE host::*) syntax?

PaperBirdMaster
  • 12,806
  • 9
  • 48
  • 94

2 Answers2

3

TYPE host::* is a pointer to a class data member. TYPE is the type of the class member and host::* means pointer to member of host. So TYPE host::* accepts a pointer to any of member of host

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • So why `void my_test(void() S::*)` does not accept a pointer to any `void()` member of `S`? – PaperBirdMaster Jan 27 '16 at 17:27
  • @PaperBirdMaster As far as a know a pointer to a class data member and a pointer to a class member function are to different things. I have never seen a they syntax you are trying to use in any code I have ever seen. – NathanOliver Jan 27 '16 at 17:32
  • @PaperBirdMaster I have been testing and I don't think C++ allows this. see: http://coliru.stacked-crooked.com/a/5db4e74c2be52aaf – NathanOliver Jan 27 '16 at 17:48
  • I've tested the code of [p0172r0](http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0172r0.html) in [Wandbox](http://melpon.org/wandbox/permlink/qmhjOsxx3gJP33wz) with gcc 6.0.0. – PaperBirdMaster Jan 27 '16 at 18:00
  • @PaperBirdMaster That is interesting. I'll have to dig into it a little later. – NathanOliver Jan 27 '16 at 18:02
  • NathanOliver you had the opportunity to take a look at this? – PaperBirdMaster Feb 03 '16 at 08:23
  • @PaperBirdMaster I have but I can't quite figure it out. I would have to ask an SO question to get some clarification on what I am seeing. I can give you the information and you can ask it since it is your problem . – NathanOliver Feb 04 '16 at 13:37
1

Try this instead:

constexpr void my_test(void (S::*)()) {}

That is the correct way to declare a parameter typed pointer to member function of S returning void with no parameters.

http://ideone.com/EqfYmb

imreal
  • 10,178
  • 2
  • 32
  • 48
  • So if `my_test(void (S::*)())` is the correct way to declare pointer to `void()` member `S`, shouldnt `template constexpr bool test(TYPE host::*)` be `template constexpr bool test(TYPE (host::*)())`? I don't understand the syntax on [p0172r0](http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0172r0.html). – PaperBirdMaster Jan 27 '16 at 17:36
  • @PaperBirdMaster I think it is possible to "split" the type like you say, because of the template deduction rules. – imreal Jan 27 '16 at 17:43