Some ideas about dot operator overloding.

Sample 1:

class C { 
public:
 int get() { return 1; }
};

int operator . square(const C& r) 
{
     return r.get() * r.get();   
}

int main()
{
  C c;
  c.square(); //ok
  square(c);  //ok
}

Sample 2:

What happens if C::square exists?

class C { 
public:
 int get() { return 1; }

  int square() const
  {
     return r.get() * r.get();   
  }
};

//Error, ambiguous C already have C::square
int operator . square(const C& r) 
{
     return r.get() * r.get();   
}

Sample 3:

Enabling uniform call.

class C { 
public:
 int get() { return 1; }

  int square() const
  {
     return r.get() * r.get();   
  }
};

using int operator . square(const C& r);

int main()
{
  C c;
  c.square(); //ok
  square(c);  //ok
}

Sample 3:

Uniform call not enabled.

class C { 
public:
 int get() { return 1; }

  int square() const
  {
     return r.get() * r.get();   
  }
};

int main()
{
  C c;
  c.square(); //ok
  square(c);  //error
}

Sample 4:

For non-class types.

std::string operator . tostring(int i)
{
...
}

int main()
{
  int i = 1;
  std::string s = i.tostring();
}

Sample 5:

Syntax alternatives

class C { 
public:
 int get() { return 1; }
};

int operator C::square() const
{
     return this.get() * this.get();   
}

References

How Non-Member Functions Improve Encapsulation - Scott Meyers

Uniform Function Call Syntax - Walter Bright

comp.lang.c++.moderated

FAQ Stroustrup