Topic: Access functions - v.x() versus v.x


Author: David R Tribble <david@tribble.com>
Date: 2000/07/12
Raw View
Silvan Greverus wrote:
>
> One of the things I really DON'T like are the parentheses needed for
> calling access member functions like the following:
>
> class vector3D {
> public:
>    double c[3];
>
>    double &x() { return c[0]; }
>    double &y() { return c[1]; }
>    double &z() { return c[2]; }
>    // ...
> };
>
> vector3D v;
> v.x()=3.0;
> v.y()=4.0;
> v.z()=5.0;
>
> cout << v.x() << "," << v.y() << "," << v.z()
>
> Have there been proposals to get around this for the C++ standard. If
> yes - why were these proposals rejected.

FWIW, Eiffel allows parentheses to be dropped if the called member
function takes no parameters.  In C++ terms, this would look like:

    class Foo
    {
        int   bar();
        ...
    };

    void func(Foo &f)
    {
        int   i;

        i = f.bar();    // okay
        i = f.bar;      // also okay (Eiffel)
    }

This might work for C++, except that there would be ambiguity between
calling a function with no args (without parentheses) and taking its
address.  Unless, of course, we require an explicit '&' operator
to take the address of functions; this is already a requirement for
member functions, but not for all functions.

    pf = &f.bar;    // address of f.bar()
    i  = f.bar;     // call to f.bar()

This leads to a question: Can the omission of the empty parentheses
be applied to any function call, or only non-static member functions?

--
David R. Tribble, mailto:david@tribble.com, http://david.tribble.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Steve Clamage <stephen.clamage@sun.com>
Date: 2000/07/09
Raw View
Michael Migal wrote:
>
> what if you have the following:
>
> class vector3D {
>
>  public:
>     double c[3];
>
>     double & operator x() { return c[0]; }
>     double & operator y() { return c[1]; }
>     double & operator z() { return c[2]; }
>
>     double x;
>     double y;
>     double z;
>  };
>
> How would the compiler to know if the expression: double temp=vector.x; is
> meant for the function or the variable x?

It doesn't have to know.  A class can't have a function member and a
data member with the same name.  Refer to 3.3 paragraph 4.

--
Steve Clamage, stephen.clamage@sun.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: llewellyat@dbritschdot.dsldot.xmissiondot.com
Date: 2000/07/09
Raw View
Christopher Eltschka <celtschk@physik.tu-muenchen.de> writes:

[snip]
> One possibility to add this to the standard with minimal change
> would be to add an extra implicit conversion which converts
> a pointer to function taking no arguments into the return value
> by calling the pointed-to function. The same would be true for
> function "pointers" written as obj.memfun.
> Of course, this conversion cannot be reversed by static_cast.
>
> I think this addition would not break any current program
> (since currently there's no implicit conversion at all on
> function pointers, all programs which would need one are
> now illegal, and all those which don't need one wouldn't
> change their meaning, since no conversion is always better
> than conversion).
>
[examples snipped]

hm.... what about this:

int& foo();

typedef int&(*Pf)();

int qux(int* i);

int qux(Pf p);

int main()
  {
    //Which qux gets called here?
    //Does foo() get called?
    qux(&foo);
  }

?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 2000/07/10
Raw View
llewellyat@dbritschdot.dsldot.xmissiondot.com wrote:
>
> Christopher Eltschka <celtschk@physik.tu-muenchen.de> writes:
>
> [snip]
> > One possibility to add this to the standard with minimal change
> > would be to add an extra implicit conversion which converts
> > a pointer to function taking no arguments into the return value
> > by calling the pointed-to function. The same would be true for
> > function "pointers" written as obj.memfun.
> > Of course, this conversion cannot be reversed by static_cast.
> >
> > I think this addition would not break any current program
> > (since currently there's no implicit conversion at all on
> > function pointers, all programs which would need one are
> > now illegal, and all those which don't need one wouldn't
> > change their meaning, since no conversion is always better
> > than conversion).
> >
> [examples snipped]
>
> hm.... what about this:
>
> int& foo();
>
> typedef int&(*Pf)();
>
> int qux(int* i);
>
> int qux(Pf p);
>
> int main()
>   {
>     //Which qux gets called here?
>     //Does foo() get called?
>     qux(&foo);
>   }
>
> ?

Ok, change "function pointers" to "functions and function pointers".
Then everything is clear:

Possibility 1:

int() -> no conversion -> take address

Possibility 2:

int() -> return value conversion -> take address

Now, no conversion is better than return value conversion,
and therefore the first rule is chosen.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Silvan Greverus <silvan@greverus.de>
Date: 2000/07/11
Raw View
Christopher Eltschka <celtschk@physik.tu-muenchen.de> writes:

[snip]
> One possibility to add this to the standard with minimal change
> would be to add an extra implicit conversion which converts
> a pointer to function taking no arguments into the return value
> by calling the pointed-to function. The same would be true for
> function "pointers" written as obj.memfun.
> Of course, this conversion cannot be reversed by static_cast.
>
> I think this addition would not break any current program
> (since currently there's no implicit conversion at all on
> function pointers, all programs which would need one are
> now illegal, and all those which don't need one wouldn't
> change their meaning, since no conversion is always better
> than conversion).
>
[examples snipped]

That is an interesting idea, but there may be some problems with it ( see
article from <llewellyat@dbritschdot.dsldot.xmissiondot.com>)

A similar way is shown in the following example:

#include <cstdio>
#include <cstddef>
#include <cmath>
#include <iostream>

#define PI 3.1415926535
#define DEG2RAD (180.0/PI)  // Factor degrees -> radians
#define RAD2DEG (PI/180.0)  // Factor radians -> degrees

using namespace std;

#define interfaceBegin(base,name)                                       \
                                                                        \
   class name ## Interface;                                             \
   friend class name ## Interface;                                      \
                                                                        \
   class name ## Interface {                                            \
                                                                        \
      friend class base;                                                \
                                                                        \
      name ## Interface() {}                                            \
                                                                        \
      name ## Interface(const name ## Interface &) {}                   \
                                                                        \
      base *__this()                                                    \
                                                                        \
      {   return reinterpret_cast<base *>                               \
                 (reinterpret_cast<char *>(this)-offsetof(base,name));  \
      }

#define interfaceEnd(base,name)                                         \
      };                                                                \
                                                                        \
      name ## Interface name;

class vector {

   double _c[3];

   double _GetRadius()

   {  return sqrt(_c[0]*_c[0]+_c[1]*_c[1]);
   }

   void _SetRadius(double v);

   double _GetAngle()

   {  return atan2(_c[1],_c[0])*RAD2DEG;
   }

   void _SetAngle(double v);

public:

   vector()

   {
   }

   vector(double x, double y)

   {  _c[0]=x; _c[1]=y;
   }

   double &operator [] (int i)

   {  return _c[i];
   }

   interfaceBegin(vector,x)

   public:
      operator double &()

      {  return __this()->_c[0];
      }

   interfaceEnd(vector,x)

   interfaceBegin(vector,y)

   public:
      operator double &()

      {  return __this()->_c[1];
      }

   interfaceEnd(vector,y)

   interfaceBegin(vector,r)

   public:

      operator double ()

      {  return __this()->_GetRadius();
      }

      double operator = (double v)

      {  __this()->_SetRadius(v);
         return v;
      }

   interfaceEnd(vector,r)

   interfaceBegin(vector,a)

   public:

      operator double ()

      {  return __this()->_GetAngle();
      }

      double operator = (double v)

      {  __this()->_SetAngle(v);
         return v;
      }

   interfaceEnd(vector,a)
};

void vector::_SetRadius(double v)

{  if (_c[0] || _c[1]) {
      v=v/_GetRadius();
      _c[0]*=v; _c[1]*=v; }
   else
      _c[0]=v;
}

void vector::_SetAngle(double v)

{  double vr,rd;

   vr=v*DEG2RAD; // angle in radians
   rd=_GetRadius();
   _c[0]=rd*cos(vr); _c[1]=rd*sin(vr);
}

int main(int, char **)

{  vector v;

   cout << "sizeof(vector)=" << sizeof(vector) <<
            "  3*sizeof(double)=" << (3*sizeof(double)) << '\n';

   v.x=4.0; v.y=3.0;

   cout << "v.x=" << v.x << "  v.y=" << v.y << '\n';
   cout << "v.r=" << v.r << "  v.a=" << v.a << '\n';

   v.r=10.0; v.a=45.0;

   cout << "v.x=" << v.x << "  v.y=" << v.y << '\n';
   cout << "v.r=" << v.r << "  v.a=" << v.a << '\n';

   return 0;
}

Except for the quite complex syntax there is one problem with this
approach: sizeof(vector) is NOT 3*sizeof(double) as one would expect from
a class like this. Too use constructs like this there should be a
standard way to create classes with sizeof(...)==0. For classes with
sizeof()==0 pointer arithmetic should be treated like it is done with
void *.

I think interface classes are usefull not only to solve the problem with
"()" (that could be handled easier by using "operator" or something
similar - see my original article). A rewrite of the above example with
interface classes could look like the following:

class vector {

   double _c[3];

public:

   vector()

   {
   }

   vector(double x, double y)

   {  _c[0]=x; _c[1]=y;
   }

   double &operator [] (int i)

   {  return _c[i];
   }

   interface { // no class name required

   public:
      operator double &()

      {  return _c[0];
      }

   } x;

   interface { // no class name required

   public:
      operator double &()

      {  return _c[1];
      }

   } y;

   interface rInterface {

   public:

      operator double ()

      {  return sqrt(_c[0]*_c[0]+_c[1]*_c[1]);
      }

      double operator = (double v);

   } r;

   interface aInterface {

   public:

      operator double ()

      {  return atan2(c[1],c[0]*RAD2DEG;
      }

      double operator = (double v);

   } a;
};

double vector::rInterface::operator = (double v)

{  if (_c[0] || _c[1]) {
      v=v/_GetRadius();
      _c[0]*=v; _c[1]*=v; }
   else
      _c[0]=v;

   return v;
}

double vector::aInterface::operator = (double v)

{  double rd,vr;

   vr=v*DEG2RAD; // angle in radians
   rd=r;
   _c[0]=rd*cos(vr); _c[1]=rd*sin(vr);

   return v;
}

The implementation would be like I have shown with "#define" above. Of
course sizeof(aInterface) etc. should be 0.



Silvan

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Bill Wade" <bill.wade@stoner.com>
Date: 2000/07/11
Raw View
"Christopher Eltschka" <celtschk@physik.tu-muenchen.de> wrote

> One possibility to add this to the standard with minimal change
> would be to add an extra implicit conversion which converts
> a pointer to function taking no arguments into the return value
> by calling the pointed-to function.

> Examples:
>
> int f();

Some might find this confusing:
  int z1 = 0;
  const int z2 = 0;    // This is a null pointer constant in C++
  (f == z1)    // Would mean (f() == 0);
  (f == z2)    // Would continue to mean (&f == (int(*)()) NULL);



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Silvan Greverus <silvan@greverus.de>
Date: 2000/07/06
Raw View
One of the things I really DON'T like are the parentheses needed for
calling access member functions like the following:

std::list<int>  li;

if (li.size()==0) {
   //     }
else {
   //     }

// --------------------------------------------------------

double d;
float f;
//
if (d>numeric_limits<float>::min()) throw overflow_error;
f=d;

//     but

int e;
//
if (e>numeric_limits<float>::max_exponent) throw overflow_error;

// --------------------------------------------------------

class vector3D {

public:
   double c[3];

   double &x() { return c[0]; }
   double &y() { return c[1]; }
   double &z() { return c[2]; }

   //
};

//
vector3D v;
v.x()=3.0;
v.y()=4.0;
v.z()=5.0;

cout << v.x() << "," << v.y() << "," << v.z()

// --------------------------------------------------------

Have there been proposals to get around this for the C++ standard. If yes
- why were these proposals rejected.

One possibility I could think of would be the following:

class vector3D {

public:
   double c[3];

   double & operator x() { return c[0]; }
   double & operator y() { return c[1]; }
   double & operator z() { return c[2]; }

   //
};

//
vector3D v;
v.x=3.0;
v.y=4.0;
v.z=5.0;

cout << v.x << "," << v.y << "," << v.z;

// --------------------------------------------------------

This use of "operator" could be extended to allow special assignment
operators:

class vector2D {

public:
   double c[2];

   double & operator x() { return c[0]; }
   double & operator y() { return c[1]; }

   double operator a() { return atan2(y,x);    } // polar angle
   double operator r() { return sqrt(x*x+y*y); } // polar radius

   double operator a = (double);
   double operator r = (double);

   //
};

double vector2D::operator a = (double v)

{  double h;

   h=r; x=h*sin(a); y=h*cos(a);

   return v;
}

double vector2D::operator r = (double v)

{  double f;

   if (x!=0.0 && y!=0.0) {
      f=v/r; x*=f; y*=f; }
   else
      x=v;

   return v;
}

//
vector2D v;
v.x=3.0;
v.y=4.0;

cout << v.r; // -> 5.0

// --------------------------------------------------------

With MSVC the previous example could be written as

class vector2D {

public:
   double c[2];

   double getX() { return c[0]; }
   double getY() { return c[1]; }

   double putX(double v) { c[0]=v; return v; }
   double putY(double v) { c[1]=v; return v; }


   __declspec(property(get=getX, put=putX)) double x;
   __declspec(property(get=getY, put=putY)) double y;

   double getA() { return atan2(y,x);    } // polar angle
   double getR() { return sqrt(x*x+y*y); } // polar radius

   double putA(double);
   double putR(double);

   __declspec(property(get=getA, put=putA)) double a;
   __declspec(property(get=getR, put=putR)) double r;


   //
};

double vector2D::putA(double v)

{  double h;

   h=r; x=h*sin(a); y=h*cos(a);

   return v;
}

double vector2D::putR(double v)

{  double f;

   if (x!=0.0 && y!=0.0) {
      f=v/r; x*=f; y*=f; }
   else
      x=r;

   return v;
}

Are there other compilers that support anything like that?


Silvan Greverus

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Michael Migal" <migal@emedius.com>
Date: 2000/07/06
Raw View
what if you have the following:

class vector3D {

 public:
    double c[3];

    double & operator x() { return c[0]; }
    double & operator y() { return c[1]; }
    double & operator z() { return c[2]; }

    double x;
    double y;
    double z;
 };

How would the compiler to know if the expression: double temp=vector.x; is
meant for the function or the variable x?

Mike

"Silvan Greverus" <silvan@greverus.de> wrote in message
news:MPG.13cc69f2ebd8aa27989680@personalnews.de.uu.net...
> One of the things I really DON'T like are the parentheses needed for
> calling access member functions like the following:
>
> std::list<int>  li;
> .
> if (li.size()==0)

>    // . }
> else {
>    // . }
>
> // --------------------------------------------------------
>
> double d;
> float f;
> // .
> if (d>numeric_limits<float>::min()) throw overflow_error;
> f=d;
>
> // . but .
>
> int e;
> // .
> if (e>numeric_limits<float>::max_exponent) throw overflow_error;
>
> // --------------------------------------------------------
>
> class vector3D {
>
> public:
>    double c[3];
>
>    double &x() { return c[0]; }
>    double &y() { return c[1]; }
>    double &z() { return c[2]; }
>
>    // .
> };
>
> // .
> vector3D v;
> v.x()=3.0;
> v.y()=4.0;
> v.z()=5.0;
>
> cout << v.x() << "," << v.y() << "," << v.z()
>
> // --------------------------------------------------------
>
> Have there been proposals to get around this for the C++ standard. If yes
> - why were these proposals rejected.
>
> One possibility I could think of would be the following:
>
> class vector3D {
>
> public:
>    double c[3];
>
>    double & operator x() { return c[0]; }
>    double & operator y() { return c[1]; }
>    double & operator z() { return c[2]; }
>
>    // .
> };
>
> // .
> vector3D v;
> v.x=3.0;
> v.y=4.0;
> v.z=5.0;
>
> cout << v.x << "," << v.y << "," << v.z;
>
> // --------------------------------------------------------
>
> This use of "operator" could be extended to allow special assignment
> operators:
>
> class vector2D {
>
> public:
>    double c[2];
>
>    double & operator x() { return c[0]; }
>    double & operator y() { return c[1]; }
>
>    double operator a() { return atan2(y,x);    } // polar angle
>    double operator r() { return sqrt(x*x+y*y); } // polar radius
>
>    double operator a = (double);
>    double operator r = (double);
>
>    // .
> };
>
> double vector2D::operator a = (double v)
>
> {  double h;
>
>    h=r; x=h*sin(a); y=h*cos(a);
>
>    return v;
> }
>
> double vector2D::operator r = (double v)
>
> {  double f;
>
>    if (x!=0.0 && y!=0.0)

>       f=v/r; x*=f; y*=f; }
>    else
>       x=v;
>
>    return v;
> }
>
> // .
> vector2D v;
> v.x=3.0;
> v.y=4.0;
>
> cout << v.r; // -> 5.0
>
> // --------------------------------------------------------
>
> With MSVC the previous example could be written as
>
> class vector2D {
>
> public:
>    double c[2];
>
>    double getX() { return c[0]; }
>    double getY() { return c[1]; }
>
>    double putX(double v) { c[0]=v; return v; }
>    double putY(double v) { c[1]=v; return v; }
>
>
>    __declspec(property(get=getX, put=putX)) double x;
>    __declspec(property(get=getY, put=putY)) double y;
>
>    double getA() { return atan2(y,x);    } // polar angle
>    double getR() { return sqrt(x*x+y*y); } // polar radius
>
>    double putA(double);
>    double putR(double);
>
>    __declspec(property(get=getA, put=putA)) double a;
>    __declspec(property(get=getR, put=putR)) double r;
>
>
>    //
> };
>
> double vector2D::putA(double v)
>
> {  double h;
>
>    h=r; x=h*sin(a); y=h*cos(a);
>
>    return v;
> }
>
> double vector2D::putR(double v)
>
> {  double f;
>
>    if (x!=0.0 && y!=0.0)

>       f=v/r; x*=f; y*=f; }
>    else
>       x=r;
>
>    return v;
> }
>
> Are there other compilers that support anything like that?
>
>
> Silvan Greverus
>
> ---
> [ comp.std.c++ is moderated.  To submit articles, try just posting with ]
> [ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
> [              --- Please see the FAQ before posting. ---               ]
> [ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]
>
>

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Silvan Greverus <silvan@greverus.de>
Date: 2000/07/07
Raw View
Mike Migail <migal@emedius.com> wrote:

> what if you have the following:
>
> class vector3D {
>
>  public:
>     double c[3];
>
>     double & operator x() { return c[0]; }
>     double & operator y() { return c[1]; }
>     double & operator z() { return c[2]; }
>
>     double x;
>     double y;
>     double z;
>  };
>
> How would the compiler to know if the expression: double temp=vector.x; is
> meant for the function or the variable x?
>
> Mike

The compiler should not allow "operator x" and "double x" at the same
scope. By the way MSVC does not allow the following class declaration.

class xClass {

public:

   double x() { return 0.0; }

   double x;

};

And I think this should be the standard. At least something like that
could be a problem outside of class declarations:

double x() { return 0.0; }

double x;

extern void aFunc(int, ...);

// ...

aFunc(3,x); // double x or address of x() ?????

Silvan

>
> "Silvan Greverus" <silvan@greverus.de> wrote in message
> news:MPG.13cc69f2ebd8aa27989680@personalnews.de.uu.net...
> > One of the things I really DON'T like are the parentheses needed for
> > calling access member functions like the following:
> >
> > std::list<int>  li;
> > .
> > if (li.size()==0)
>
> >    // . }
> > else {
> >    // . }
> >
> > ....
> > Have there been proposals to get around this for the C++ standard. If yes
> > - why were these proposals rejected.
> >
> > One possibility I could think of would be the following:
> >
> > class vector3D {
> >
> > public:
> >    double c[3];
> >
> >    double & operator x() { return c[0]; }
> >    double & operator y() { return c[1]; }
> >    double & operator z() { return c[2]; }
> >
> >    // .
> > };
> >
> > // .
> > vector3D v;
> > v.x=3.0;
> > v.y=4.0;
> > v.z=5.0;
> >
> > cout << v.x << "," << v.y << "," << v.z;
> >


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 2000/07/08
Raw View
Silvan Greverus wrote:
>
> One of the things I really DON'T like are the parentheses needed for
> calling access member functions like the following:
>
> std::list<int>  li;
> ?
> if (li.size()==0) {
>    // ? }
> else {
>    // ? }
>
> // --------------------------------------------------------
>
> double d;
> float f;
> // ?
> if (d>numeric_limits<float>::min()) throw overflow_error;
> f=d;
>
> // ? but ?
>
> int e;
> // ?
> if (e>numeric_limits<float>::max_exponent) throw overflow_error;
>
> // --------------------------------------------------------
>
> class vector3D {
>
> public:
>    double c[3];
>
>    double &x() { return c[0]; }
>    double &y() { return c[1]; }
>    double &z() { return c[2]; }
>
>    // ?
> };
>
> // ?
> vector3D v;
> v.x()=3.0;
> v.y()=4.0;
> v.z()=5.0;
>
> cout << v.x() << "," << v.y() << "," << v.z()
>
> // --------------------------------------------------------

One possibility to add this to the standard with minimal change
would be to add an extra implicit conversion which converts
a pointer to function taking no arguments into the return value
by calling the pointed-to function. The same would be true for
function "pointers" written as obj.memfun.
Of course, this conversion cannot be reversed by static_cast.

I think this addition would not break any current program
(since currently there's no implicit conversion at all on
function pointers, all programs which would need one are
now illegal, and all those which don't need one wouldn't
change their meaning, since no conversion is always better
than conversion).

Examples:

int f();

int (*pf)();
int i;

pf = f; // usual function pointer assignment - no conversion needed
i = f; // automatic conversion to int; same as i = f(int);

void foo(void(*)());
void foo(int);

foo(f); // chooses first foo, due to better match

void bar(int);

bar(f); // same as bar(f());

struct X { int f(); } x;

int k = x.f; // same as x.f();

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]