std::abs ambiguity

K

Kaba

Hi,

Anyone knows why the 'abs' function is ambiguous here? Tried to compile
with both Visual Studio 2008 Sp1 and Comeau. Ignore the fact that
Own::abs does not do the right thing.

The way I see it, the Standard Library abs should be in namespace std,
the Koenig lookup shouldn't activate for native types, and thus there
should be no ambiguity.

#include <cmath>

namespace Own
{

float abs(float x)
{
return x;
}

}

using namespace Own;

int main()
{
float a = 5;
float b = 3;
float c = abs(a - b);

return 0;
}
 
R

red floyd

Kaba said:
Hi,

Anyone knows why the 'abs' function is ambiguous here? Tried to compile
with both Visual Studio 2008 Sp1 and Comeau. Ignore the fact that
Own::abs does not do the right thing.

The way I see it, the Standard Library abs should be in namespace std,
the Koenig lookup shouldn't activate for native types, and thus there
should be no ambiguity.

#include <cmath>

namespace Own
{

float abs(float x)
{
return x;
}

}

using namespace Own;

int main()
{
float a = 5;
float b = 3;
float c = abs(a - b);

return 0;
}

Most implementations also put the Standard C library routines into the
global namespace as well.
 
K

Kaba

red said:
Most implementations also put the Standard C library routines into the
global namespace as well.

Thanks. Better to avoid using names from Standard Library then...
 
J

joshuamaurice

Or perhaps better avoid using "using namespace xxx"?

Both are probably good ideas considering he'd hit the same problem if
the call to abs was in the same namespace as his abs function.
 
F

Fred Zwarts

Kaba said:
Hi,

Anyone knows why the 'abs' function is ambiguous here? Tried to compile
with both Visual Studio 2008 Sp1 and Comeau. Ignore the fact that
Own::abs does not do the right thing.

The way I see it, the Standard Library abs should be in namespace std,
the Koenig lookup shouldn't activate for native types, and thus there
should be no ambiguity.

#include <cmath>

namespace Own
{

float abs(float x)
{
return x;
}

}

using namespace Own;

int main()
{
float a = 5;
float b = 3;
float c = abs(a - b);

return 0;
}

The g++ compiler under Suse Linux (x86_64) Enterprise 10 handles this without any message.
Maybe your compiler needs a switch to make it standard conforming.
 
K

Kaba

Fred said:
The g++ compiler under Suse Linux (x86_64) Enterprise 10 handles this without any message.
Maybe your compiler needs a switch to make it standard conforming.

I have already disabled language extensions. I suspect this is something
that is there because of some historical reasons. Most often, the Comeau
compiler acts correctly. That it doesn't hints towards a good reason to
do so.
 
J

James Kanze

I have already disabled language extensions. I suspect this is
something that is there because of some historical reasons.
Most often, the Comeau compiler acts correctly. That it
doesn't hints towards a good reason to do so.

It depends on the library implementation.

Note that this is one place where C and C++ different, despite
the fact that <cmath> is a "C" library header. In C, there is
no function "abs" in <math.h>. And the one in <stdlib.h> only
takes int, so would be a less good match. Roughly speaking, I
think an implementation can take three approaches:

-- It is fully conforming, all of the functions in the <c...>
header are in namespace std::, and only in namespace std::.
The program is legal.

For a number of reasons, this is the case for very few
implementations of the library, and none of the widespread
ones.

-- It puts all of the names in the <c...> headers in :: as
well. Systematically. This is the case for Dinkumware, for
example.

-- Some of the functions (most of those directly inherited from
C) are in both :: and std::, others (typically the overloads
introduced by C++) are only in std::. This seems to be the
most frequent implementation, even if it results in some
incoherence.

The next version of the standard will make all three approaches
legal. So it's anyone's guess as to whether a given bit of code
will actually work on another compiler or not.
 
J

joshuamaurice

 -- It is fully conforming, all of the functions in the <c...>
    header are in namespace std::, and only in namespace std::.
    The program is legal.

    For a number of reasons, this is the case for very few
    implementations of the library, and none of the widespread
    ones.

 -- It puts all of the names in the <c...> headers in :: as
    well.  Systematically.  This is the case for Dinkumware, for
    example.

 -- Some of the functions (most of those directly inherited from
    C) are in both :: and std::, others (typically the overloads
    introduced by C++) are only in std::.  This seems to be the
    most frequent implementation, even if it results in some
    incoherence.

The next version of the standard will make all three approaches
legal.  So it's anyone's guess as to whether a given bit of code
will actually work on another compiler or not.

Really? That seems most atrocious.
 
J

James Kanze

Really? That seems most atrocious.

It's already the case for a lot of other things. Ideally, one
would like the same rule as in C---a header is allowed to define
what it is required to define, and nothing else. Practically,
that's not implementable---you can't very well define
std::vector (in <vector>) without a definition for the default
allocator (in <memory>) or std::reverse_iterator (in
<iterator>); if the compiler doesn't support export, you
might also need <new> (or more likely, <memory> requires <new>,
so you get it indirectly). So the rule was adopted that any C++
header can include any other. So there are all sorts of code
which compiles with one implementation, and not with another,
because the author forgot to include a header.
 
C

Christopher Dearlove

Roughly speaking, I
think an implementation can take three approaches:

<snipped other two>

-- Some of the functions (most of those directly inherited from
C) are in both :: and std::, others (typically the overloads
introduced by C++) are only in std::. This seems to be the
most frequent implementation, even if it results in some
incoherence.

What does/will be allowed to do an implementation taking this
route for the overloads introduced by C++ when including the
*.h form of the headers (which I believe you recently recommended)?

I'm struggling to see how it could include the overloads in the *.h
file - where they should be in :: - but leaves them only in std:: in the
c* header, without going out of its way to do that, meaning that
someone sees an advantage in the above approach for other than
ease of implementation.

Or I'm missing something.
 
A

Alf P. Steinbach

* Christopher Dearlove:
Roughly speaking, I
think an implementation can take three approaches:

<snipped other two>

-- Some of the functions (most of those directly inherited from
C) are in both :: and std::, others (typically the overloads
introduced by C++) are only in std::. This seems to be the
most frequent implementation, even if it results in some
incoherence.

What does/will be allowed to do an implementation taking this
route for the overloads introduced by C++ when including the
*.h form of the headers (which I believe you recently recommended)?

It's allowed in C++0x, that's the whole point of the change: to allow the
existing practice.

Specifically, the C++0x draft language regarding [xxx.h] in §D.5 is

<quote>
2 Every C header, each of which has a name of the form name.h, behaves as if
each name placed in the standard library namespace by the corresponding cname
header is placed within the global namespace scope. It is unspecified whether
these names are first declared or defined within namespace scope (3.3.5) of the
namespace std and are then injected into the global namespace scope by explicit
using-declarations (7.3.3).
3 [Example: The header <cstdlib> assuredly provides its declarations and
definitions within the namespace std. It may also provide these names within the
global namespace. The header <stdlib.h> assuredly provides the same declarations
and definitions within the global namespace, much as in the C Standard. It may
also provide these names within the namespace std. —endexample]
</quote>

I think it's a bit unclear what the "library namespace" is.

As with C++98, the non-normative example is more clear than the normative text!

I'm struggling to see how it could include the overloads in the *.h
file - where they should be in :: - but leaves them only in std:: in the
c* header, without going out of its way to do that, meaning that
someone sees an advantage in the above approach for other than
ease of implementation.

You're talking about an implementation conforming to C++98?

One approach I can think of is to use two helper headers [basic_c_xxx.h] and
[basic_cpp_xxx.h]. Then [cxxx] includes both those. [xxx.h] includes
[basic_c_xxx.h], and also includes [basic_cpp_xxx.h] if this is C++. It may play
around with macro definitions to remove [basic_c_xxx.h] namespace'ing when the
language is C. When the language is C++ it uses 'using' directives to bring the
names from some internal namespace and into the global namespace.

Assuming that works nicely, and I can't see why not, it isn't difficult. As is
oft stated, the solution to every computer science problem is indirection. :)

Or I'm missing something.

Dunno, dunno even if I understood your question, but


Cheers, & hth.,

- Alf
 
C

Christopher Dearlove

Alf P. Steinbach said:
You're talking about an implementation conforming to C++98?

I was talking about de facto C++98 and de jure C++0X according to James's
third model.
Assuming that works nicely, and I can't see why not, it isn't difficult.
As is oft stated, the solution to every computer science problem is
indirection. :)

There's enough detail there for me to see how to do it. Why anyone
would want to do it (as you are deliberately setting out to follow that
model rather than the other two) is less clear, though I suppose it may
relate to being able to compile more C programs written not aware of
C++ with a C++ compiler (those using abs in various ways for example).

Thanks.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top