title: Why is the value of a pointer-to-member always the same for different members of the same struct?
body: <p>I have the following code:</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;string&gt;
  
  using namespace std;
  
  struct foo_s {
      string a;
      string b;
      string c;
  };
  
  void print_field(foo_s* foo, string foo_s::* field) {
      cout &lt;&lt; "field: " &lt;&lt; field &lt;&lt; " - " &lt;&lt; foo-&gt;*field &lt;&lt; endl;
  }
  
  int main() {
     foo_s my_foo = {
         "a",
         "b",
         "c",
     };
  
     print_field(&amp;my_foo, &amp;foo_s::a);
     print_field(&amp;my_foo, &amp;foo_s::b);
     print_field(&amp;my_foo, &amp;foo_s::c);
  
     return 0;
  }
  </code></pre>
  
  <p>Its output is:</p>
  
  <pre><code>field: 1 - a                                                                                                                                                                                                              
  field: 1 - b                                                                                                                                                                                                              
  field: 1 - c  
  </code></pre>
  
  <p>I'm having a bit of trouble understanding the specifics of what's going on in the <code>print_field()</code> function.  Namely:</p>
  
  <ol>
  <li>What's the type of <code>field</code>? I imagine it's <code>pointer-to-string-foo_s-member</code></li>
  <li>Why is the value of <code>field</code> always the same (1 in this case), yet <code>foo-&gt;*field</code> yields different results?</li>
  </ol>
  
  <p>Mainly, I'm baffled at #2. I imagined field would be an "offset" from the start of the struct and <code>foo-&gt;*field</code> would have been conceptually equivalent to something like</p>
  
  <pre><code>char* ptr = static_cast&lt;char*&gt;(foo);
  ptrdiff_t offset = somehow_get_the_byte_offset_from_pointer_to_member(field);
  ptr = ptr[offset];
  string result = *static_cast&lt;string*&gt;(ptr);
  </code></pre>
  
  <p>but that seems to be out since <code>field</code>'s value doesn't vary across calls. What am I missing? How exactly is this specific operation described by the standard?</p>