3

In reference to May pointer to members circumvent the access level of a member?, I would like to understand the code snippet in that question.

I will paste the code snippet here.

#include <iostream>

template<typename Tag, typename Tag::type M>
struct Rob { 
  friend typename Tag::type get(Tag) {
    return M;
  }
};

// use
struct A {
  A(int a):a(a) { }
private:
  int a;
};

// tag used to access A::a
struct A_f { 
  typedef int A::*type;
  friend type get(A_f);
};

template struct Rob<A_f, &A::a>;

int main() {
  A a(42);
  std::cout << "proof: " << a.*get(A_f()) << std::endl;
}

Among a few questions, I highlight a single question here that may crack open the rest.

I do not understand the following statement in the main function:

a.*get(A_f())

I do understand (I think) that get(A_F()) returns a pointer to a.a. However, I do not understand the get() function. In what struct is this actually defined? How is it being accessed in that struct?

I have two secondary questions that may be answered if the above question is answered, but I will place them here. First, in the definition of Rob, the friend keyword is being used in front of the function get that is being defined, as well as declared. I thought that the friend keyword can only be used in front of a function declaration to indicate that a function defined elsewhere has access to the private/protected members of the class. Can someone explain?

Second, I do not understand the line template struct Rob<A_f, &A::a>;. I do not understand the use of the template keyword without <...>, and I do not understand why there is no template definition - this seems to be some sort of forward declaration. Can someone explain? Thanks.

Community
  • 1
  • 1
Dan Nissenbaum
  • 13,558
  • 21
  • 105
  • 181

1 Answers1

2

However, I do not understand the get() function. In what struct is this actually defined? How is it being accessed in that struct?

First thing first: the functionget() is a friend of both A and Rob class template. It is not a member function of any class. It is rather a free function.

Now, where exactly is this free function defined? Well it is defined in Rob class template, and at the same time it is declared as friend of Rob class template.

I thought that the friend keyword can only be used in front of a function declaration to indicate that a function defined elsewhere has access to the private/protected members of the class. Can someone explain?

Yes it can be declared friend of a class, without defining it inside the class. It can also be defined inside a class and at the same time can be declared friend of that class. In your case, it is actually defined in the class itself.

Second, I do not understand the line template struct Rob<A_f, &A::a>;.

That is called explicit instantiation of the class template with the given tempate arguments. You can see many other syntax to explicitly instantiate a template here (well if it is a function template):

Community
  • 1
  • 1
Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • Thank you. I have looked carefully at the link and nested links you provided. I'm close to understanding this. Can you please tell me how you know, from the syntax, that `template struct Rob;` is an instantiation, and not the declaration for a template specialization? – Dan Nissenbaum Mar 28 '12 at 16:39
  • @DanNissenbaum: Because I know the syntaxes of both template specialization and template explicit instantiation. Their syntaxes are not same; they're different, so I know which is which. – Nawaz Mar 28 '12 at 16:46
  • Nawaz - a thoroughly rude response. – Dan Nissenbaum Mar 28 '12 at 16:50
  • @DanNissenbaum: That is not rude. If that is rude, then lets say this: how do you know that `int i;` is a declaration of variable `i`? or Lets say, how do you know that `i` is a variable in the syntax `int i;`, and how do you know that `i` is not a function? Please answer my questions :-) – Nawaz Mar 28 '12 at 16:52
  • `i` is a variable in `int i;` because the `int` keyword prepends it. Second, `i` is a variable in `int i;` because `i` appears after the built-in type keyword `int`. Third, `i` is not a function because there are no parentheses that follow `i` in the statement `int i;`. Perhaps now you could answer my question, which is not as trivial? Thanks. – Dan Nissenbaum Mar 28 '12 at 16:57
  • 1
    @DanNissenbaum: An explicit specialization begins with `template<>`, and an explicit instantiation just begins with `template`. – Mike Seymour Mar 28 '12 at 16:58
  • @DanNissenbaum: `int` keyword prepends it, so what is great about that? How exactly do you know that if that is really a variable? – Nawaz Mar 28 '12 at 17:02
  • @Nawaz: Short is all I needed - not a full discussion, but something to point the way. Please stop acting rudely. – Dan Nissenbaum Mar 28 '12 at 17:04
  • @DanNissenbaum: That is TOO JUDGEMENTAL. All I'm trying to make you realize that there is nothing rude in my first comment, because I know that you would answer my question, saying *"because I know that"*, and there is nothing rude in saying that. – Nawaz Mar 28 '12 at 17:06