Topic: Proposal: class-scoped non-member functions


Author: llewelly.at@xmission.dot.com (llewelly)
Date: Tue, 24 Jun 2003 03:39:18 +0000 (UTC)
Raw View
xleobx@qmailcomq.com writes:
[snip]
> Well, the devil is in the details, but I'd like to see an ability
> to enhance the public interface of a class without contortions.
[snip]

This is what non-member functions are for.

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: llewelly.at@xmission.dot.com (llewelly)
Date: Tue, 24 Jun 2003 03:39:44 +0000 (UTC)
Raw View
xleobx@qmailcomq.com writes:

> Suppose you want to write a function that performs some operation on
> an object (using only its public interface, naturally). Currently
> such a function is usually declared as
>
> return_type foo(cv_opt TYPE & object, args...) {
>  ... object.something_or_other(...)
>  ... object.something_else(...)
>  ...
> }
>
> What I am proposing, while essentially being a syntactical sugar,
> provides better readability and ease of refactoring:
>
> return_type TYPE::foo(args...) cv_opt {
>  ... something_or_other(...)
>  ... something_else(...)
>  ...
> }
[snip]

Please no. The infelicities of member function syntax cause enough
    problems. Let no similar syntax be added to c++.

Further, since you plan only to use the public interface to implement
    the new operation, why is a non-member function unsuitable?

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: brangdon@cix.co.uk (Dave Harris)
Date: Tue, 24 Jun 2003 03:42:28 +0000 (UTC)
Raw View
s.moleski@tcu.edu ("Sebastian Moleski") wrote (abridged):
> So, how does that stop somebody from adding a new function to
> the public interface of a foreign class and thus get access to
> all its private members?

He says (or implies) that the new function can access only public members.
I think he also intends that the new function cannot be virtual. I don't
know what he intends if there's a name clash:

    struct Derived;
    void Derived::v();

    struct Base {
        virtual void v();
    };

    struct Derived: Base {
    };

    void Derived::v() {
    }

    void test() {
        Derived d;
        d.v(); // Base::v() or Derived::v()?
    }

Probably it would need to be a compile-time error. But where?

    void test2() {
        Derived d;
        d.Base::v();
    }

is arguably OK, so perhaps the declarations should be allowed and the
point-of-call flagged. I can't say I'm really comfortable with any of
this, though.

-- Dave Harris, Nottingham, UK

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: tslettebo@chello.no.nospam (=?Windows-1252?Q?Terje_Sletteb=F8?=)
Date: Thu, 19 Jun 2003 02:24:44 +0000 (UTC)
Raw View
><xleobx@qmailcomq.com> wrote in message
news:RmPHa.52$FA5.4932@iad-read.news.verio.net...
>> Suppose you want to write a function that performs some operation on
>> an object (using only its public interface, naturally). Currently
>> such a function is usually declared as
>>
>> return_type foo(cv_opt TYPE & object, args...) {
>> ... object.something_or_other(...)
>> ... object.something_else(...)
>> ...
>> }
>>
>> What I am proposing, while essentially being a syntactical sugar,
>> provides better readability and ease of refactoring:
>>
>> return_type TYPE::foo(args...) cv_opt {
>> ... something_or_other(...)
>> ... something_else(...)
>> ...
>> }

>Terje Sletteb=F8:
>
>However, I'm wondering, in your suggestion, where did the "object"
>variable go? How is it accessed in the function, and what's its name?

Oops, I understand the suggestion better now. The function behaves as a
member function in this case. Well, then the suggestion adds something.

It could be a little amusing to pair it with the suggestion I mentioned
in the other posting:

class A { ... }; // No f() declared here

void A::f(...) { ... }

A object;

object.f();

There's still the issue of possible ODR, and possible confusion, though,
although the latter might be said for the other suggestion, as well.


Regards,

Terje

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: xleobx@qmailcomq.com
Date: Fri, 20 Jun 2003 01:52:22 +0000 (UTC)
Raw View
Terje Sletteb? <tslettebo@chello.no.nospam> wrote:
>>> What I am proposing, while essentially being a syntactical sugar,
>>> provides better readability and ease of refactoring:
>>>
>>> return_type TYPE::foo(args...) cv_opt {
>>> ... something_or_other(...)
>>> ... something_else(...)
>>> ...
>>> }

>>Terje Sletteb?:
>>
>>However, I'm wondering, in your suggestion, where did the "object"
>>variable go? How is it accessed in the function, and what's its name?

Have you posted a message and then canceled it? I do not see it.

> Oops, I understand the suggestion better now. The function behaves as a
> member function in this case. Well, then the suggestion adds something.

Exactly. It enhances the public interface of a class without the need
to modify the definition of a class.

> It could be a little amusing to pair it with the suggestion I mentioned
> in the other posting:

I'll have to hope that "the other posting" appears eventually.

> class A { ... }; // No f() declared here

> void A::f(...) { ... }

> A object;

> object.f();

That is what I had in mind; I apologize for not making
it clear enough. The usage of such a function should be
indistinguishable from the usage of a method.

> There's still the issue of possible ODR, and possible confusion, though,

Same with any outlined definition of a method, if no tricks are played
or such tricks (see below) are illegal.

> although the latter might be said for the other suggestion, as well.

Confusion as in "Where does that method come from? It is not declared
within the class"? Right now it is confusing, but if adopted, it will
be part of the language and much less confusing than some other arcane
parts of it.

A reasonable question is, what namespace should such a function belong to,
if any?

Could you do

namespace X {
class A { ... };
}

namespace Y {

namespace X { class A { void f(); }; }

void X::A::f() { ... } // Defines Y::X::A::f

void ::X::A::f() { ... } // defines a class-scoped function (1)
}

namespace Z {
void X::A::f() { ... } // OK (may be useful with Koenig lookup), or
   // an error because of (1)?
}

X::A object;
object.f();

More questions arise: how can you take a pointer to such a
function, and how do you refer to it?

void (X::A::*pf)() = Y::::X::A::f; // Isn't it ugly?

Well, the devil is in the details, but I'd like to see an ability
to enhance the public interface of a class without contortions.

 Leo (axe X's and quash Q's)

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: tslettebo@chello.no.nospam (=?Windows-1252?Q?Terje_Sletteb=F8?=)
Date: Fri, 20 Jun 2003 19:37:55 +0000 (UTC)
Raw View
<xleobx@qmailcomq.com> wrote in message
news:RmPHa.52$FA5.4932@iad-read.news.verio.net...
> Suppose you want to write a function that performs some operation on
> an object (using only its public interface, naturally). Currently
> such a function is usually declared as
>
> return_type foo(cv_opt TYPE & object, args...) {
> ... object.something_or_other(...)
> ... object.something_else(...)
> ...
> }
>
> What I am proposing, while essentially being a syntactical sugar,
> provides better readability and ease of refactoring:
>
> return_type TYPE::foo(args...) cv_opt {
> ... something_or_other(...)
> ... something_else(...)
> ...
> }

What if the function performs an operation on more than one type?:

void f(type_a, type_b) { ... ]

The above doesn't look more readable to me (or easier to refactor). The
syntax scope::name in C++ means you're referring to a name in the given
scope. As the name in this case is _not_ in the given scope (not a class
member), this would be just confusing, rather than clarifying.

There's no need to show that a function operates on a given type, as
it's clear from the signature.

However, I'm wondering, in your suggestion, where did the "object"
variable go? How is it accessed in the function, and what's its name?

> This looks exactly as an outline definition of a class method,
> but, absent of a declaration of a method with matching prototype
> within the the class TYPE definition, becomes a class-scoped
non-member
> function.

This could be dangerous. If the class is later changed to contain the
same function, you get an ODR violation on the extra definition.

There's been a related proposal, though, to be able to _call_ functions
as if it's a member function, so the calling syntax is the same for
member and non-member functions. E.g.:

void f(const type &object) { ... }

This may be called as:

type object;

f(object);

or:

object.f();

I think that's a good proposal, as it would in essence allow you to
extend a type's interface, without modifying the class.


Regards,

Terje

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: s.moleski@tcu.edu ("Sebastian Moleski")
Date: Fri, 20 Jun 2003 19:42:37 +0000 (UTC)
Raw View
<xleobx@qmailcomq.com> wrote in message
news:4rnIa.76$FA5.6348@iad-read.news.verio.net...
> Well, the devil is in the details, but I'd like to see an ability
> to enhance the public interface of a class without contortions.

So, how does that stop somebody from adding a new function to the public
interface of a foreign class and thus get access to all its private members?
The access control mechanism becomes rather useless, if it's that easy to
circumvent it.

sm


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: xleobx@qmailcomq.com
Date: Wed, 18 Jun 2003 03:02:34 +0000 (UTC)
Raw View
Suppose you want to write a function that performs some operation on
an object (using only its public interface, naturally). Currently
such a function is usually declared as

return_type foo(cv_opt TYPE & object, args...) {
 ... object.something_or_other(...)
 ... object.something_else(...)
 ...
}

What I am proposing, while essentially being a syntactical sugar,
provides better readability and ease of refactoring:

return_type TYPE::foo(args...) cv_opt {
 ... something_or_other(...)
 ... something_else(...)
 ...
}

This looks exactly as an outline definition of a class method,
but, absent of a declaration of a method with matching prototype
within the the class TYPE definition, becomes a class-scoped non-member
function. Such a function can-be forward-declared:

return_type TYPE::foo(args...);

E.g.:

class A;

void A::foo(); // OK, forward-declares a class-scoped function

void A::bar();  // OK so far, but see below (1)

void A::zzz() { } // error: A is incomplete

class A {

public:
 void bar(); // warning (or error) referring to line (1):
  // class-scoped function declaration will be ignored
 void baz();
};

void A::baz(); // error: declaration of `void A::baz()'
  // outside of class is not definition

void A::foo() { ... }
 // OK, defining a previously declared class-scoped function

void A::foo2() { ... }
 // OK, defining a class-scoped function

I have not found anything similar in Google archives on comp.std.c++, so,
if this has been discussed and rejected before, please point me to a thread.

Regards,
 Leo (omit x's and q's)

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]