Topic: Using p->() to call operator() when p is pointer.


Author: "Tom s" <NULL@NULL.NULL>
Date: 24 Apr 2006 01:10:05 GMT
Raw View
> The (*p)() syntax is, imho, rather ugly.

If you use it enough, you won't care. How many people like function
pointers when they first seem them? Use them once or twice and you stop
caring. Same thing with references to arrays. That's just the way you get
things done. Try returning a reference to an array:

int ( &Func() )[5]
{
    static int monkey[5] = {};

    return monkey;
}

If you'd prefer "normal syntax" rather than "pointer syntax", then just do
the following:

void SomeFunc( SomeClass* p )
{
    SomeClass &object = *p;

    //Now use "object" instead

    object();
}

---
[ 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://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Lance Diduck" <lancediduck@nyc.rr.com>
Date: 24 Apr 2006 01:10:08 GMT
Raw View
operator -> is a "indirect member-selection" operator. operator() is a
"function call" operator
The other "member selection" operator is the direct (non-overloadable)
operator. (operator -dot)

You can think of it this way: to invoke a method on an object, you must

a) use operator -> on an indrect reference (e.g. pointer) and name the
member to invoke explicity, e.g.
object_indirectref(op indirectmemberselect)methodname(op function call)
p->operator()();
b) use operator . on a direct (non assignable) reference and name the
member to invoke explicity, e.g.
object_directref(op directmemberselect)methodname(op function call)
p.operator()(); or (*p).operator()();
c) if the method name is an overloaded operator then the
directmemberselect AND methodnames are subject to special sytnax rules
that are designed to closely emulate C syntax
object_directref(op function call)
(*p)()

Rule C is why the directmemberselect operator is not overloadable. And
by extension, why the indirectmemberselect does not have special syntax
rules applied (other than one saying that operator -> is special in
that overloaded versions will subsequenly have the builtlin version
applied, so that when you write a smart-pointer, so one would not have
to write (smart_ptrobj->)->method();)



But yes this has been discussed before, in fact in Stroustrup D&E. But
it never hurts to duscuss it again, and explain it again, to help hone
ones ability to explain and teach C++.

But the main objection to ever more implict constructions like this is
that it make the final program text impervious to analysis, which mean
less effective compiler diagnostics. And it is hard enough getting
meaningful syntax error messages as it is.

---
[ 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://www.comeaucomputing.com/csc/faq.html                      ]





Author: "SuperKoko" <tabkannaz@yahoo.fr>
Date: Sun, 23 Apr 2006 20:09:17 CST
Raw View
"Johann 'Myrkraverk' Oskarsson" wrote:
> Hi,
>
> This is my first post here, on comp.std.c++, and I hope my question
> isn't too naive, or if it's been discussed before ;P
>
> Is there any fundamental reason why I shouldn't be able to use p->()
> to call operator() when p is a pointer to a function object?  The
> (*p)() syntax is, imho, rather ugly.
>
-> is a binary operator which excepts an identifier as second
parameter.
The correct syntax is:
p->operator()();

Basically, what you ask would be to create a postfix -> operator,
having the same meaning than the prefix * operator.
Thus (p->) would be the same than (*p)

Accepting the syntax p->() for (*p)() would be a pain for the lexical
analyzer...

In fact, p->(x) could only be sensibly interpreted as using the binary
operator->
(p->)(x) would be interpreted as using the unary operator->

IMHO (p->)(x) is not more readable than (*p)(x)

---
[ 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://www.comeaucomputing.com/csc/faq.html                      ]





Author: myrkraverk@yahoo.com ("Johann 'Myrkraverk' Oskarsson")
Date: Mon, 24 Apr 2006 01:34:32 GMT
Raw View
"Lance Diduck" <lancediduck@nyc.rr.com> writes:

Ok, I'm trying to digest these explanations ;)

> But yes this has been discussed before, in fact in Stroustrup
> D&E. But it never hurts to duscuss it again, and explain it again,
> to help hone ones ability to explain and teach C++.

Well, in C, it was deemed common enough to use pointers to have a
special indirect member select operator ( -> ), so I guess this
discussion comes down to: are function object pointers common enough
to warrant a special operator for indirect function calls ( eg. ->()
)?  I'm not sure it is, and even though the (*p)() syntax is ugly, it
*is* the C syntax when it comes to function pointers.

That said, I probably need to read the relevant chapter in
Stroustrup's D&E ;)

> But the main objection to ever more implict constructions like this
> is that it make the final program text impervious to analysis, which
> mean less effective compiler diagnostics. And it is hard enough
> getting meaningful syntax error messages as it is.

Good point, but as I mentioned above, ->() can also be made into an
operator of its own.  But that doesn't mean it'll change anything,
after all, I'm a n00b in language/compiler design ;)


Johann

--
johann myrkraverk com (you know the drill with the @ and .)
I classify Outlook mail as spam, use something else.

---
[ 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://www.comeaucomputing.com/csc/faq.html                      ]





Author: avakar@volny.cz (=?ISO-8859-1?Q?Martin_Vejn=E1r?=)
Date: Tue, 25 Apr 2006 04:31:43 GMT
Raw View
Johann 'Myrkraverk' Oskarsson wrote:
> Well, in C, it was deemed common enough to use pointers to have a
> special indirect member select operator ( -> ), so I guess this
> discussion comes down to: are function object pointers common enough
> to warrant a special operator for indirect function calls ( eg. ->()
> )?  I'm not sure it is, and even though the (*p)() syntax is ugly, it
> *is* the C syntax when it comes to function pointers.

I would understand the need for "->" operator in C++, where you can
overload it to change its semantics. I don't see what difference would
it make in C, if "." operator was used in place of "->".

Now, while "->" can be used both on pointers and on other objects, the
"()" operator cannot. So, there wouldn't really be any need to define
some sort of operator "->()", would there? Why not simply define "p()"
to be equivalent to "(*p)()" whenever "p" is a pointer?

--
Martin

---
[ 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://www.comeaucomputing.com/csc/faq.html                      ]





Author: musiphil@bawi.org (Seungbeom Kim)
Date: Tue, 25 Apr 2006 16:35:05 GMT
Raw View
Lance Diduck wrote:
> operator -> is a "indirect member-selection" operator. operator() is a
> "function call" operator
> The other "member selection" operator is the direct (non-overloadable)
> operator. (operator -dot)
>
> You can think of it this way: to invoke a method on an object, you must
>
> a) use operator -> on an indrect reference (e.g. pointer) and name the
> member to invoke explicity, e.g.
> object_indirectref(op indirectmemberselect)methodname(op function call)
> p->operator()();
> b) use operator . on a direct (non assignable) reference and name the
> member to invoke explicity, e.g.
> object_directref(op directmemberselect)methodname(op function call)
> p.operator()(); or (*p).operator()();
> c) if the method name is an overloaded operator then the
> directmemberselect AND methodnames are subject to special sytnax rules
> that are designed to closely emulate C syntax
> object_directref(op function call)
> (*p)()
>
> Rule C is why the directmemberselect operator is not overloadable. And
> by extension, why the indirectmemberselect does not have special syntax
> rules applied (other than one saying that operator -> is special in
> that overloaded versions will subsequenly have the builtlin version
> applied, so that when you write a smart-pointer, so one would not have
> to write (smart_ptrobj->)->method();)

I think what the OP meant was just having "p->()" as a shorthand, a
syntactic sugar for "(*p)()".. wasn't it?

I can understand the need, which I think many people who have some
experience in Perl will agree. :) In Perl, if $p is a reference
(the Perl version of a pointer) to an array or a hash or a function,
you can write $p->[1], $p->{"John"}, or $p->(1, "John"), respectively.

Having operator() leads to shorter expressions in most cases, but if
what you have is a pointer or an iterator, it can lead to "ugly"
(*p)(...) or p->operator()(...) and you may just as well give name it
like p->f(...) instead. :) If the OP's suggestion were accepted, you
could still have operator() and write p->(...).

--
Seungbeom Kim

---
[ 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://www.comeaucomputing.com/csc/faq.html                      ]





Author: "SuperKoko" <tabkannaz@yahoo.fr>
Date: Tue, 25 Apr 2006 13:23:22 CST
Raw View
Martin Vejn   r wrote:
> I would understand the need for "->" operator in C++, where you can
> overload it to change its semantics. I don't see what difference would
> it make in C, if "." operator was used in place of "->".
>
In C, since a pointer has no member, the same syntax '.' could be
used...
C++ inherited from that, and, by pure luck, it was a really good thing!
First, in C++, a pointer has a member : Namely, its destuctor.
That makes possible to put pointers in containers such as std::vector,
which internally, calls explicitly destructors.
Like that, there is a difference between:
p.~P(); // P is the type of the pointer
p->~T(); // T is the type of the pointed value.

But, there is much more... There has been lot of smart pointers
(std::auto_ptr, boost::shared_ptr, various clone_ptr and other
smart_ptr).
Most of these pointers have members, and can be included in containers,
and behave sensibly.
All that, is only possible because of the distinction between operator.
and operator->
Pointers syntax is really good in C++ (references syntax too... so,
there are separate references and pointers).

C choosed to use a not very convenient, but rigourous syntax (i.e. you
really state what you mean), and IMHO, it has been miracurously
successful when transposed to C++.

Here I say that "C choosed". But that is not exact. This is more an
historical detail than a true choice.
Early C compilers had very bad type checking (C is the evolution of B :
a typeless language), and structure accesses were not checked.
What means that:

struct {int x;};
int *p,*q,x;
p.x=&x; /* compiler accepted that, and this code is equivalent to :
p=&x */
p->x=42; /* different meaning */

If you don't believe me, have a look at the "printf" function described
as an example, at the end of the C reference manual (1975):
http://cm.bell-labs.com/cm/cs/who/dmr/cman.pdf

That "feature" is used in order to simulate an union type.

In a typeless language, such as B, the usage context specifies exactly
how an operation is performed.
Early C has basically this same characteristic.

Also, I'm not sure that using operator. instead of operator-> would be
good when manipulating pointer to pointers.
That may be confusing (I can't be sure, since we have no experience on
that syntax) to have (**p).x equivalent to (*p).x, and p[3].x
equivalent to (*p[3]).x (but different of (*p)[3].x).
That may avoid the diagnosis of typo errors (i.e. the programmer forgot
a '*', but the compiler does not complain, and the implicit
dereferencement is at the wrong place).

> Now, while "->" can be used both on pointers and on other objects, the
> "()" operator cannot. So, there wouldn't really be any need to define
> some sort of operator "->()", would there? Why not simply define "p()"
> to be equivalent to "(*p)()" whenever "p" is a pointer?
>
It could be a good idea... knowing that pointer to functions (good old
pointer to functions) already allow that syntax.
But the main problem with that, is the impossibility (nowaydays) to
provide such feature for user-defined smart pointer types (knowing that
the number of arguments that operator() can take is not known).
It could be possible, if there was a special compiler facility, similar
to the overloading of operator->, but applied to operator()().
It would also restrict the possibility of having an operator() applied
to a smart pointer type (the pointer itself, not the pointed-to data).
So, this syntaxic sugar probably does not worth it.

Here too, I'd like to say that we have been lucky.
The original syntaxic sugar for function pointers has revealed to be
very good when writing templates accepting functors (though, perhaps,
function references would do the work too).
Here too, this special syntax is due to historical reasons.

In B, all functions names refered to variables pointing to functions.
So, the function-call syntax was "func(parameters)" where func was a
rvalue interpreted as a function pointer.
Similarly, the array-to-pointer conversions were introduced in C for
compatibility with B.

In B, an array was a pointer to the data.
For instance:

auto arr 4; /* perhaps auto arr[4] on more recent B compilers */

allocates a memory word for the variable (arr), and makes it point to
an array of 4 words, automatically allocated.

The equivalent C code is:
int arr_hidden[4];
int* arr=arr_hidden;

That explains the semantics of function pointers and arrays in C.

Note that, function pointer syntax, and operator-> syntax "works" well
with C++ templates (by pure luck?), but array semantics doesn't agree
at all with C++ templates.
Fortunately, boost::array correct these problems.

Note : On the other side, ALGOL68 use coercions rules for assignments
of reference to values, values to references, references to references
and values to values.
The same syntax is used for all these form of assignment, but the
compiler automatically understand what must be done.


---
[ 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://www.comeaucomputing.com/csc/faq.html                      ]





Author: johnchx2@yahoo.com
Date: Tue, 25 Apr 2006 15:49:03 CST
Raw View
"Johann 'Myrkraverk' Oskarsson" wrote:

> Well, in C, it was deemed common enough to use pointers to have a
> special indirect member select operator ( -> ), so I guess this
> discussion comes down to: are function object pointers common enough
> to warrant a special operator for indirect function calls ( eg. ->()
> )?

I would tend to suspect not, because most C++ function objects I've run
across are typically passed by value or by reference.  Standard
algorithms like for_each() and transform() take function objects by
value, while constructors of containers like std::map take their
comparison function by reference.

That doesn't mean that there aren't function objects passed around by
pointer, but I suspect that common practice parallels the standard
library.  (boost::function, for example, wraps a function object passed
by value or by reference.)

It's worth pointing out that, in C++, a pointer to a function *is* a
function object.  That is, the following is legal:

  int foo() {return 0;}
  int ( * fptr )() = &foo;
  int i = fptr();   // no dereference needed

This means that passing a function pointer *is* passing a function
object by value.

---
[ 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://www.comeaucomputing.com/csc/faq.html                      ]





Author: =?ISO-8859-1?Q?Martin_Vejn=E1r?= <avakar@volny.cz>
Date: Wed, 26 Apr 2006 11:35:17 CST
Raw View
SuperKoko wrote:
> Martin Vejn   r wrote:
>> Now, while "->" can be used both on pointers and on other objects, the
>> "()" operator cannot. So, there wouldn't really be any need to define
>> some sort of operator "->()", would there? Why not simply define "p()"
>> to be equivalent to "(*p)()" whenever "p" is a pointer?
>>
> It could be a good idea... knowing that pointer to functions (good old
> pointer to functions) already allow that syntax.
> But the main problem with that, is the impossibility (nowaydays) to
> provide such feature for user-defined smart pointer types (knowing that
> the number of arguments that operator() can take is not known).
> It could be possible, if there was a special compiler facility, similar
> to the overloading of operator->, but applied to operator()().
> It would also restrict the possibility of having an operator() applied
> to a smart pointer type (the pointer itself, not the pointed-to data).
> So, this syntaxic sugar probably does not worth it.

You're trying to say that it would be hard to make "p()" equivalent to
"(*p)()", when "p" is a smart-pointer. Indeed it would, the reason is
hidden in [13.3.1.1.2] which for some reason doesn't take function
objects into consideration.

The following example is well-formed:

     void bar() {}
     struct Foo
     {
         typedef void (*pfn_t)();
         operator pfn_t () { return bar; }
     };
     int main()
     {
         Foo foo;
         foo();
     }

In main, in call to "foo", the overload resolution considers "void
(pfn_t e) { e(); }" as a candidate function. The following example,
however, is ill-formed.

     struct Bar
     {
         void operator () () {}
     };
     struct Foo
     {
         Bar bar;
         operator Bar* () { return &bar; }
     };
     int main()
     {
         Foo foo;
         foo();
     }

If the overload resolution used "void (Bar *b) { b->operator()(); }" as
a candidate function, all would be fine. The smart pointer would merely
need an implicit conversion to its underlying type and function call
syntax would work.

--
Martin

---
[ 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://www.comeaucomputing.com/csc/faq.html                      ]





Author: "SuperKoko" <tabkannaz@yahoo.fr>
Date: Wed, 26 Apr 2006 16:00:49 CST
Raw View
Martin Vejn   r wrote:
> SuperKoko wrote:
> > Martin Vejn   r wrote:
> >> Now, while "->" can be used both on pointers and on other objects, the
> >> "()" operator cannot. So, there wouldn't really be any need to define
> >> some sort of operator "->()", would there? Why not simply define "p()"
> >> to be equivalent to "(*p)()" whenever "p" is a pointer?
> >>
> > It could be a good idea... knowing that pointer to functions (good old
> > pointer to functions) already allow that syntax.
> > But the main problem with that, is the impossibility (nowaydays) to
> > provide such feature for user-defined smart pointer types (knowing that
> > the number of arguments that operator() can take is not known).
> > It could be possible, if there was a special compiler facility, similar
> > to the overloading of operator->, but applied to operator()().
> > It would also restrict the possibility of having an operator() applied
> > to a smart pointer type (the pointer itself, not the pointed-to data).
> > So, this syntaxic sugar probably does not worth it.
>
> You're trying to say that it would be hard to make "p()" equivalent to
> "(*p)()", when "p" is a smart-pointer. Indeed it would, the reason is
> hidden in [13.3.1.1.2] which for some reason doesn't take function
> objects into consideration.
>
> The following example is well-formed:
>
>      void bar() {}
>      struct Foo
>      {
>          typedef void (*pfn_t)();
>          operator pfn_t () { return bar; }
>      };
>      int main()
>      {
>          Foo foo;
>          foo();
>      }
>
> In main, in call to "foo", the overload resolution considers "void
> (pfn_t e) { e(); }" as a candidate function. The following example,
> however, is ill-formed.
>
>      struct Bar
>      {
>          void operator () () {}
>      };
>      struct Foo
>      {
>          Bar bar;
>          operator Bar* () { return &bar; }
>      };
>      int main()
>      {
>          Foo foo;
>          foo();
>      }
>
> If the overload resolution used "void (Bar *b) { b->operator()(); }" as
> a candidate function, all would be fine. The smart pointer would merely
> need an implicit conversion to its underlying type and function call
> syntax would work.
>
The idea is good...
That one would be equivalent:
      struct Bar
      {
          void operator () () {}
      };
      struct Foo
      {
          Bar bar;
          operator Bar& () { return bar; }
      };
      int main()
      {
          Foo foo;
          foo(); // Bar would be candidate for overload resolution.
      }
Based, on the principle that raw pointers would have this "conversion
operator overload", and that overload resolution would, transitively
parse these operators, your code above, would be equivalent.

I'm sure that it could be a powerful tool for generic ways of wrapping
functors...
It is that point that could make it an interesting proposition for the
next C++ standard, knowing that pure syntaxic sugar in seldom contexts,
in itself doesn't worth a language change... otherwise there would be
far too many changes!


---
[ 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://www.comeaucomputing.com/csc/faq.html                      ]





Author: myrkraverk@yahoo.com ("Johann 'Myrkraverk' Oskarsson")
Date: Sun, 23 Apr 2006 04:45:45 GMT
Raw View
Hi,

This is my first post here, on comp.std.c++, and I hope my question
isn't too naive, or if it's been discussed before ;P

Is there any fundamental reason why I shouldn't be able to use p->()
to call operator() when p is a pointer to a function object?  The
(*p)() syntax is, imho, rather ugly.

>From Stroustrup, I see that -> and () have the same precedence, and
with left to right assiciativity of -> (and () ?) this should work,
right?  Or am I naive?

My apologies if this has already been discussed for the updated
standard,


Johann

--
johann myrkraverk com (you know the drill with the @ and .)
I classify Outlook mail as spam, use something else.

---
[ 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://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Lance Diduck" <lancediduck@nyc.rr.com>
Date: 23 Apr 2006 17:40:06 GMT
Raw View
operator -> is a "indirect member-selection" operator. operator() is a
"function call" operator
The other "member selection" operator is the direct (non-overloadable)
operator. (operator -dot)

You can think of it this way: to invoke a method on an object, you must

a) use operator -> on an indrect reference (e.g. pointer) and name the
member to invoke explicity, e.g.
object_indirectref(op indirectmemberselect)methodname(op function call)
p->operator()();
b) use operator . on a direct (non assignable) reference and name the
member to invoke explicity, e.g.
object_directref(op directmemberselect)methodname(op function call)
p.operator()(); or (*p).operator()();
c) if the method name is an overloaded operator then the
directmemberselect AND methodnames are subject to special sytnax rules
that are designed to closely emulate C syntax
object_directref(op function call)
(*p)()

Rule C is why the directmemberselect operator is not overloadable. And
by extension, why the indirectmemberselect does not have special syntax
rules applied (other than one saying that operator -> is special in
that overloaded versions will subsequenly have the builtlin version
applied, so that when you write a smart-pointer, so one would not have
to write (smart_ptrobj->)->method();)



But yes this has been discussed before, in fact in Stroustrup D&E. But
it never hurts to duscuss it again, and explain it again, to help hone
ones ability to explain and teach C++.

But the main objection to ever more implict constructions like this is
that it make the final program text impervious to analysis, which mean
less effective compiler diagnostics. And it is hard enough getting
meaningful syntax error messages as it is.

---
[ 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://www.comeaucomputing.com/csc/faq.html                      ]