Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > C++ reluctant to overload function

Reply
Thread Tools

C++ reluctant to overload function

 
 
Keith H Duggar
Guest
Posts: n/a
 
      10-13-2010
On Oct 13, 12:33*pm, Pete Becker <(E-Mail Removed)> wrote:
> On 2010-10-13 11:59:29 -0400, Steve Pope said:
> > The whole idea of overloading is to provide the programmer with
> > a form of polymorphism. *e.g. I have a math library function

>
> > double sin(double x)

>
> > And I want to overloaded it with a vector version

>
> > vector<double> sin(vector<double> x)

>
> > Because one scope encloses the other I cannot do this without some
> > sort of workaround.

>
> Did you try this? Add #include <math.h> and it should work just fine.
>
> Or, if you're a namespace purist, use #include <cmath>


Aren't the compatibility .h headers deprecated by the C++ standard?
(See Annex 0).

> and put your function in namespace std like the rest of the math functions.


Since his specialization does not depend on any user defined
type, and also since sin is not a template anyhow (?) (and so
can't qualify for the template specialization exception below)
wouldn't your advice result in undefined behavior?

17.3.3.1 Reserved names
[lib.reserved.names]

1 It is undefined for a C++ program to add declarations or
definitions
to namespace std or namespaces within namespace std unless
otherwise
specified. A program may add template specializations for any
stan-
dard library template to namespace std. Such a specialization
(com-
plete or partial) of a standard library template results in
undefined
behaviour unless the declaration depends on a user-defined name
of
external linkage and unless the specialization meets the
standard
library requirements for the original template.20)

KHD
 
Reply With Quote
 
 
 
 
Johannes Schaub (litb)
Guest
Posts: n/a
 
      10-13-2010
Victor Bazarov wrote:

> On 10/13/2010 11:52 AM, Johannes Schaub (litb) wrote:
>> James Kanze wrote:
>>
>>> On Oct 12, 10:40 pm, (E-Mail Removed) (Steve Pope) wrote:
>>>> Victor Bazarov<(E-Mail Removed)> wrote:
>>>>> On 10/12/2010 3:09 PM, Steve Pope wrote:
>>>>>> Victor Bazarov<(E-Mail Removed)> wrote:
>>>>>>> Rationale for what, exactly? For the rules of hiding?
>>>>>>> Names defined in a closer scope hide names defined in the
>>>>>>> outer scope. It's an old rule, that AFAICT existed from
>>>>>>> the start in C++. For example,
>>>>>>> int main()
>>>>>>> {
>>>>>>> double d = 3.14159;
>>>>>>> {
>>>>>>> int d = 42;
>>>>>>> {
>>>>>>> d = 666; // changes the int d, not the double d
>>>>>>> }
>>>>>>> }
>>>
>>>>>>> // here 'd' is still 3.14159
>>>>>>> }
>>>
>>>>>> Well it's not exactly analogous. In the above case the
>>>>>> name-mangled names clash, in the case I described in my
>>>>>> initial post, they do not.
>>>
>>>>> Not sure I understand what you mean here. In your example
>>>>> the name is 'foo'. In my example the name is 'd'. Would it
>>>>> make a difference if I named my variables 'foo'? What's
>>>>> "name-mangled" have to do with name resolution or with name
>>>>> hiding? And what *is* "name-mangled", anyway?
>>>
>>>> Unless I am missing something:
>>>
>>>> Overloaded function names do not hide each other because their
>>>> name-mangled names include the argument types.
>>>
>>> Overloaded function names do not hide each other because they
>>> are in the same scope. Names in the same scope never hide one
>>> another. A name in a given scope hides names in the enclosing
>>> scope. The reason you can overload functions (but not
>>> variables) is because the C++ standard allows more than one
>>> symbol to be declared in any given scope, provided all of the
>>> symbols are functions or function templates. (There's also
>>> a special provision which allows the name of a class to be
>>> declared when there is another declaration of the same name.
>>> This is, however, a hack for C compatibility purposes, and is
>>> best ignored.)
>>>

>>
>> Since I too like to argue about things - names in the same scope can
>> actually hide one another.
>>
>> struct A { };
>> void A();
>>
>> Name of function hides the name of struct.
>>
>> struct A {
>> int A;
>> };
>>
>> Name of member hides name of struct (injected class name).

>
> I'd prefer to see "nitpick" to be attached to the first sentence in your
> reply.


Whatever you want to call it, it still is a valid counter-example against
the statement that names in the same scope can't hide each other. One nit-
pick picks on another nit-pick. That's usenet.

 
Reply With Quote
 
 
 
 
Victor Bazarov
Guest
Posts: n/a
 
      10-13-2010
On 10/13/2010 12:59 PM, Johannes Schaub (litb) wrote:
> Victor Bazarov wrote:
>
>> On 10/13/2010 11:52 AM, Johannes Schaub (litb) wrote:
>>> James Kanze wrote:
>>>
>>>> On Oct 12, 10:40 pm, (E-Mail Removed) (Steve Pope) wrote:
>>>>> Victor Bazarov<(E-Mail Removed)> wrote:
>>>>>> On 10/12/2010 3:09 PM, Steve Pope wrote:
>>>>>>> Victor Bazarov<(E-Mail Removed)> wrote:
>>>>>>>> Rationale for what, exactly? For the rules of hiding?
>>>>>>>> Names defined in a closer scope hide names defined in the
>>>>>>>> outer scope. It's an old rule, that AFAICT existed from
>>>>>>>> the start in C++. For example,
>>>>>>>> int main()
>>>>>>>> {
>>>>>>>> double d = 3.14159;
>>>>>>>> {
>>>>>>>> int d = 42;
>>>>>>>> {
>>>>>>>> d = 666; // changes the int d, not the double d
>>>>>>>> }
>>>>>>>> }
>>>>
>>>>>>>> // here 'd' is still 3.14159
>>>>>>>> }
>>>>
>>>>>>> Well it's not exactly analogous. In the above case the
>>>>>>> name-mangled names clash, in the case I described in my
>>>>>>> initial post, they do not.
>>>>
>>>>>> Not sure I understand what you mean here. In your example
>>>>>> the name is 'foo'. In my example the name is 'd'. Would it
>>>>>> make a difference if I named my variables 'foo'? What's
>>>>>> "name-mangled" have to do with name resolution or with name
>>>>>> hiding? And what *is* "name-mangled", anyway?
>>>>
>>>>> Unless I am missing something:
>>>>
>>>>> Overloaded function names do not hide each other because their
>>>>> name-mangled names include the argument types.
>>>>
>>>> Overloaded function names do not hide each other because they
>>>> are in the same scope. Names in the same scope never hide one
>>>> another. A name in a given scope hides names in the enclosing
>>>> scope. The reason you can overload functions (but not
>>>> variables) is because the C++ standard allows more than one
>>>> symbol to be declared in any given scope, provided all of the
>>>> symbols are functions or function templates. (There's also

.. ^^^^^^^^^^^^
>>>> a special provision which allows the name of a class to be

.. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^
>>>> declared when there is another declaration of the same name.

.. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^
>>>> This is, however, a hack for C compatibility purposes, and is
>>>> best ignored.)
>>>>
>>>
>>> Since I too like to argue about things - names in the same scope can
>>> actually hide one another.
>>>
>>> struct A { };
>>> void A();
>>>
>>> Name of function hides the name of struct.
>>>
>>> struct A {
>>> int A;
>>> };
>>>
>>> Name of member hides name of struct (injected class name).

>>
>> I'd prefer to see "nitpick" to be attached to the first sentence in your
>> reply.

>
> Whatever you want to call it, it still is a valid counter-example against
> the statement that names in the same scope can't hide each other. One nit-
> pick picks on another nit-pick. That's usenet.


Yours wasn't really a counter-example (nor was it a nit pick, so I take
my request back). See the highlighted portion of James' post above.
The cases you presented as "hiding" are already covered by him. So, not
generally "names can hide one another" but "a name of a class can
coexist with the name of another item" - the special provision James was
talking about.

V
--
I do not respond to top-posted replies, please don't ask
 
Reply With Quote
 
Johannes Schaub (litb)
Guest
Posts: n/a
 
      10-13-2010
Victor Bazarov wrote:

> On 10/13/2010 12:59 PM, Johannes Schaub (litb) wrote:
>> Victor Bazarov wrote:
>>
>>> On 10/13/2010 11:52 AM, Johannes Schaub (litb) wrote:
>>>> James Kanze wrote:
>>>>
>>>>> On Oct 12, 10:40 pm, (E-Mail Removed) (Steve Pope) wrote:
>>>>>> Victor Bazarov<(E-Mail Removed)> wrote:
>>>>>>> On 10/12/2010 3:09 PM, Steve Pope wrote:
>>>>>>>> Victor Bazarov<(E-Mail Removed)> wrote:
>>>>>>>>> Rationale for what, exactly? For the rules of hiding?
>>>>>>>>> Names defined in a closer scope hide names defined in the
>>>>>>>>> outer scope. It's an old rule, that AFAICT existed from
>>>>>>>>> the start in C++. For example,
>>>>>>>>> int main()
>>>>>>>>> {
>>>>>>>>> double d = 3.14159;
>>>>>>>>> {
>>>>>>>>> int d = 42;
>>>>>>>>> {
>>>>>>>>> d = 666; // changes the int d, not the double d
>>>>>>>>> }
>>>>>>>>> }
>>>>>
>>>>>>>>> // here 'd' is still 3.14159
>>>>>>>>> }
>>>>>
>>>>>>>> Well it's not exactly analogous. In the above case the
>>>>>>>> name-mangled names clash, in the case I described in my
>>>>>>>> initial post, they do not.
>>>>>
>>>>>>> Not sure I understand what you mean here. In your example
>>>>>>> the name is 'foo'. In my example the name is 'd'. Would it
>>>>>>> make a difference if I named my variables 'foo'? What's
>>>>>>> "name-mangled" have to do with name resolution or with name
>>>>>>> hiding? And what *is* "name-mangled", anyway?
>>>>>
>>>>>> Unless I am missing something:
>>>>>
>>>>>> Overloaded function names do not hide each other because their
>>>>>> name-mangled names include the argument types.
>>>>>
>>>>> Overloaded function names do not hide each other because they
>>>>> are in the same scope. Names in the same scope never hide one
>>>>> another. A name in a given scope hides names in the enclosing
>>>>> scope. The reason you can overload functions (but not
>>>>> variables) is because the C++ standard allows more than one
>>>>> symbol to be declared in any given scope, provided all of the
>>>>> symbols are functions or function templates. (There's also

> . ^^^^^^^^^^^^
>>>>> a special provision which allows the name of a class to be

> . ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^
>>>>> declared when there is another declaration of the same name.

> . ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^
>>>>> This is, however, a hack for C compatibility purposes, and is
>>>>> best ignored.)
>>>>>
>>>>
>>>> Since I too like to argue about things - names in the same scope can
>>>> actually hide one another.
>>>>
>>>> struct A { };
>>>> void A();
>>>>
>>>> Name of function hides the name of struct.
>>>>
>>>> struct A {
>>>> int A;
>>>> };
>>>>
>>>> Name of member hides name of struct (injected class name).
>>>
>>> I'd prefer to see "nitpick" to be attached to the first sentence in your
>>> reply.

>>
>> Whatever you want to call it, it still is a valid counter-example against
>> the statement that names in the same scope can't hide each other. One
>> nit- pick picks on another nit-pick. That's usenet.

>
> Yours wasn't really a counter-example (nor was it a nit pick, so I take
> my request back). See the highlighted portion of James' post above.
> The cases you presented as "hiding" are already covered by him. So, not
> generally "names can hide one another" but "a name of a class can
> coexist with the name of another item" - the special provision James was
> talking about.
>


Coexistence does not nearly imply name hiding. Otherwise, overloaded
functions would hide each other.
 
Reply With Quote
 
Juha Nieminen
Guest
Posts: n/a
 
      10-13-2010
Victor Bazarov <(E-Mail Removed)> wrote:
> On 10/12/2010 12:37 PM, Juha Nieminen wrote:
>> Victor Bazarov<(E-Mail Removed)> wrote:
>>> Name lookup when in a member function finds
>>> the member 'foo' which actually *hides* any other 'foo', and that's why
>>> the '<unnamed namespace>::foo' should NOT be found during that lookup
>>> and is *not* considered an overload.

>>
>> What is the rationale for that? I can't immediately think of a reason
>> or notivation for that.

>
> Rationale for what, exactly? For the rules of hiding? Names defined in
> a closer scope hide names defined in the outer scope. It's an old rule,
> that AFAICT existed from the start in C++. For example,


foo(int) is not the same thing as foo(int,int). They are two different
functions with different signatures. In the original post one is hiding
the other. I can't understand the rationale for that.
 
Reply With Quote
 
Juha Nieminen
Guest
Posts: n/a
 
      10-13-2010
James Kanze <(E-Mail Removed)> wrote:
> On Oct 12, 5:37 pm, Juha Nieminen <(E-Mail Removed)> wrote:
>> Victor Bazarov <(E-Mail Removed)> wrote:
>> > Name lookup when in a member function finds
>> > the member 'foo' which actually *hides* any other 'foo', and that's why
>> > the '<unnamed namespace>::foo' should NOT be found during that lookup
>> > and is *not* considered an overload.

>
>> What is the rationale for that? I can't immediately think of
>> a reason or notivation for that.

>
> I suspect that the main reason is that that is how name lookup
> always works. In just about every language which recognizes
> scope. You wouldn't want to get a duplicate definition error
> because you had defined an "int foo" at namespace scope, and
> having the compiler find a function name, but not the name of
> a variable, would be extremely confusing.


A 'foo(int)' in an inner scope hiding a 'foo(int)' in the outer
scope is understandable.

However, a 'foo(int)' in the inner scope hiding a 'foo(int,int)'
in the outer scope isn't. I don't understand why it has to be hidden,
which is why I asked for the rationale for that. What would be the
problem with an unqualified call like "foo(1, 2)" calling the function
in the outer scope? It's not like it can be confused with the function
in the inner scope (because the amount of parameters is clearly
different).

> Beyond that, of course, you really don't want the compiler
> looking further than you expect. Consider for a moment:
>
> class C
> {
> void f(int);
> public:
> void g() { f('a'); }
> };
>
> When you wrote the class, it's obvious (I suppose) that you
> intended g to call C::f. And you would be most annoyed if it
> called some ::f some of the time (depending on what headers were
> included before this header), but not others. Similarly, if
> C derived from some other class, you wouldn't like the fact that
> the author of that class added a private f(char) broke your
> code.


In this example the function call would match two function
declarations, in which case the innermost scoped declaration wins.
However, if the choices are 'foo(int)' and 'foo(int,int)', what
is the reason to make the inner declaration hide the outer one?
 
Reply With Quote
 
Victor Bazarov
Guest
Posts: n/a
 
      10-13-2010
On 10/13/2010 1:21 PM, Juha Nieminen wrote:
> Victor Bazarov<(E-Mail Removed)> wrote:
>> On 10/12/2010 12:37 PM, Juha Nieminen wrote:
>>> Victor Bazarov<(E-Mail Removed)> wrote:
>>>> Name lookup when in a member function finds
>>>> the member 'foo' which actually *hides* any other 'foo', and that's why
>>>> the '<unnamed namespace>::foo' should NOT be found during that lookup
>>>> and is *not* considered an overload.
>>>
>>> What is the rationale for that? I can't immediately think of a reason
>>> or notivation for that.

>>
>> Rationale for what, exactly? For the rules of hiding? Names defined in
>> a closer scope hide names defined in the outer scope. It's an old rule,
>> that AFAICT existed from the start in C++. For example,

>
> foo(int) is not the same thing as foo(int,int). They are two different
> functions with different signatures. In the original post one is hiding
> the other. I can't understand the rationale for that.


Overloading is based on the *type* of the function, not the name,
although it does require the name to be the same. Another major
requirement for overloading is that both *names* have to be declared in
the same *scope*. In the original post the functions are declared in
different scopes, and overloading does NOT apply, and hiding does. Such
is the design of the language. What is it exactly that you don't
understand? The rationale for what?

V
--
I do not respond to top-posted replies, please don't ask
 
Reply With Quote
 
Öö Tiib
Guest
Posts: n/a
 
      10-13-2010
On 13 okt, 18:59, (E-Mail Removed) (Steve Pope) wrote:
> Öö Tiib *<(E-Mail Removed)> wrote:
>
> >Example given by Victor is on one hand a good example of name hiding
> >feature what language allows. On other hand it is hard to see who
> >really needs to hide a name like that (and why). It is very hard to
> >believe that writer of the function did really run out of possible
> >names.

>
> The whole idea of overloading is to provide the programmer with
> a form of polymorphism. *e.g. I have a math library function
>
> double sin(double x)
>
> And I want to overloaded it with a vector version
>
> vector<double> sin(vector<double> x)
>
> Because one scope encloses the other I cannot do this without some
> sort of workaround. *


I do not really see why you need them as overloads but hopefully you
tell the reason.

Lets first see what we have. There are several sin() in current C++.
1) In <complex> there is such std::sin():

namespace std
{
template<class T> complex<T> sin(const complex<T>& x);
}

2) In <valarray> there is such std::sin():

namespace std
{
template<class T> valarray<T> sin(const valarray<T>&);
}

3) In <cmath> there are such sin():

double sin(double);
float sin(float);
long double sin(long double);

Lets now see solutions.

1) These are all usable side-by-side. Just call ::sin() for double,
float and long double or std::sin() for valarray<T> and complex<T>.

2) If you want to define your own sin in your scope (namespace) and
have the C++ sin variants also there as overloads:

#include <complex>
#include <valarray>
#include <cmath>

namespace stevemath
{
using ::sin;
using std::sin;
vector<double> sin(vector<double> x);
}

3) If you want them to be all useful as overloads in a global
namespace then that is bad idea to burden global namespace but also
doable:

#include <complex>
#include <valarray>
#include <cmath>
using std::sin;
vector<double> sin(vector<double> x); // Steves sin

So what is so difficult about it?

> If the nuisance factor of such workarounds inclines
> the programmer to not use polymorphism when they should, then
> in some sense the language design is steering them to a poor design choice.


I do not understand ... why you need them all sins as overloads of
each other. If there is reason then i don not understand how can it be
so good i have not met it but you desire it without indicating it?

Majority would really hate if some of thousands of functions from
<windows.h> or other place like that started to compete in overload
resolution with member functions within their classes or with
functions within their namespace and cause typos to compile for
confusing results. Describe the poor design choice you are steered
towards. For me C++ is as liberal as it can only get when choices of
paradigms, idioms or design patterns are under discussion.
 
Reply With Quote
 
Victor Bazarov
Guest
Posts: n/a
 
      10-13-2010
On 10/13/2010 1:28 PM, Juha Nieminen wrote:
> James Kanze<(E-Mail Removed)> wrote:
>> On Oct 12, 5:37 pm, Juha Nieminen<(E-Mail Removed)> wrote:
>>> Victor Bazarov<(E-Mail Removed)> wrote:
>>>> Name lookup when in a member function finds
>>>> the member 'foo' which actually *hides* any other 'foo', and that's why
>>>> the '<unnamed namespace>::foo' should NOT be found during that lookup
>>>> and is *not* considered an overload.

>>
>>> What is the rationale for that? I can't immediately think of
>>> a reason or notivation for that.

>>
>> I suspect that the main reason is that that is how name lookup
>> always works. In just about every language which recognizes
>> scope. You wouldn't want to get a duplicate definition error
>> because you had defined an "int foo" at namespace scope, and
>> having the compiler find a function name, but not the name of
>> a variable, would be extremely confusing.

>
> A 'foo(int)' in an inner scope hiding a 'foo(int)' in the outer
> scope is understandable.
>
> However, a 'foo(int)' in the inner scope hiding a 'foo(int,int)'
> in the outer scope isn't. I don't understand why it has to be hidden,
> which is why I asked for the rationale for that.


The *rule* is that the *name* is looked up first, without the arguments.
That's how name lookup works. That's why the *name* alone hides
another name that is spelled the same way, regardless of *what the name
is of*.

> What would be the
> problem with an unqualified call like "foo(1, 2)" calling the function
> in the outer scope? It's not like it can be confused with the function
> in the inner scope (because the amount of parameters is clearly
> different).


So, what's important, the number of arguments or the number and the
types? Should 'foo(char, vector<int>*)' *hide* 'foo(int,int)' or
shouldn't it?

>> Beyond that, of course, you really don't want the compiler
>> looking further than you expect. Consider for a moment:
>>
>> class C
>> {
>> void f(int);
>> public:
>> void g() { f('a'); }
>> };
>>
>> When you wrote the class, it's obvious (I suppose) that you
>> intended g to call C::f. And you would be most annoyed if it
>> called some ::f some of the time (depending on what headers were
>> included before this header), but not others. Similarly, if
>> C derived from some other class, you wouldn't like the fact that
>> the author of that class added a private f(char) broke your
>> code.

>
> In this example the function call would match two function
> declarations, in which case the innermost scoped declaration wins.
> However, if the choices are 'foo(int)' and 'foo(int,int)', what
> is the reason to make the inner declaration hide the outer one?


The name lookup is already quite complicated. Mix in the arguments (the
number, but not the types), and you get plenty of problems that are
likely impossible to solve in a working compiler for all people to be
satisfied, I would guess.

It's easier for the language to be as strict as possible, but not
stricter. Making rules relaxed creates more problems than it solves.

V
--
I do not respond to top-posted replies, please don't ask
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      10-13-2010
On Oct 13, 5:33 pm, Pete Becker <(E-Mail Removed)> wrote:
> On 2010-10-13 11:59:29 -0400, Steve Pope said:
> > The whole idea of overloading is to provide the programmer with
> > a form of polymorphism. e.g. I have a math library function


> > double sin(double x)


> > And I want to overloaded it with a vector version


> > vector<double> sin(vector<double> x)


> > Because one scope encloses the other I cannot do this without some
> > sort of workaround.


> Did you try this? Add #include <math.h> and it should work just fine.


> Or, if you're a namespace purist, use #include <cmath> and put your
> function in namespace std like the rest of the math functions.


Technically, that's not legal. But there's nothing to prevent
you from using a few "using" declarations, to bring names into
whatever scope you want.

--
James Kanze
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: C++ reluctant to overload function James Kanze C++ 4 10-14-2010 02:12 PM
Examples of using "reluctant" subexpressions in regexps? david.karr@wamu.net Java 4 04-27-2005 07:46 PM
Help simplify complex regexp needing positive lookahead and reluctant quantifers david.karr@wamu.net Java 7 03-25-2005 09:05 PM
function overload (not operator overload) Ying-Chieh Liao Perl Misc 3 10-11-2004 11:24 AM
How use the overload of>> (or<<) of a class in the overload of << and >> of another class? Piotre Ugrumov C++ 3 01-25-2004 08:08 PM



Advertisments