why free function inside namespace is ambiguous? - c++

--myfunc.hh
#ifndef MY_FUNC_HH
#define MY_FUNC_HH
namespace abc
{
int xyz (int a, int b);
}
#endif
--myfunc.cc
#include "myfunc.hh"
using namespace abc;
int xyz (int a, int b)
{
if (!b)
return 0;
return xyz (b, b/a);
}
$ g++ -c -g myfunc.cc myfunc.hh
myfunc.cc: In function ‘int xyz(int, int)’:
myfunc.cc:9: error: call of overloaded ‘xyz(int&, int)’ is ambiguous
myfunc.cc:5: note: candidates are: int xyz(int, int)
myfunc.hh:6: note: int abc::xyz(int, int)
Why is xyz overloaded when there's only one function named xyz defined here?
isn't the using namespace abc telling the compiler to look for name xyz in namespace abc?
For example, when you use the std::copy function
#include <algorithm>
using namespace std;
void afunction()
{
copy(blah, blah, blah);
}
all works fine, why should abc::xyz be any different here? Or, is it because the recursive call? if so, why?

I think in myfunc.cc you want to write
#include "myfunc.hh"
namespace abc {
int xyz (int a, int b)
{
if (!b)
return 0;
return xyz (b, b/a);
}
}
This way you define the abc::xyz function you declared in the .h file. The way you wrote it you define an xyz function outside the namespace abc while also importing the one which was declared in the namespace. Thus the ambiguity.
Agreeing with #cHao and #JonathanWakely suggestion, I favor this better syntax:
int abc::xyz (int a, int b)
{
if (!b)
return 0;
return xyz (b, b/a);
}
Indeed it ensure that abc::xyz has been correctly declared in the header file.

There is a difference between these two codes:
-- myfunc.cc
#include "myfunc.hh"
using namespace abc;
int xyz (int a, int b)
{
if (!b)
return 0;
return xyz (b, b/a);
}
-- myfunc.cc
#include "myfunc.hh"
namespace abc {
int xyz (int a, int b)
{
if (!b)
return 0;
return xyz (b, b/a);
}
}
The first makes use of abc namespace, but xyz is defined at the "top" namespace; there are 2 functions defined. The second gives the implementation of the abc::xyz function.
In your case you want to do the second.

In your myfunc.cc file you overload the function xyz. That means you are defining a completely new function. There is one that is local in global namespace, there is one in the namespace abc.
The statement using namespace abc; in your example, introduces the ambiguity actually, rather than solving it. Your call is ambiguous in the sense that compiler have no idea which function to call.

Your question seems to be asking why there are two versions of xyz(int, int) visible when you explicitly went and told the compiler to make xyz(int, int) visible and then defined another one?
What, exactly, do you expect the compiler to do here? It isn't going to guess for you so it gives you an error.
If you need to call one or the other, use the scope operator and an explicit namespace. You could call ::xyz(1, 2) or abc::xyz(1, 2) for example.

Related

different implementations for the same function (c/c++)

is it possible to have 2 (or more) different implementations for the same function declared in a header file?
I'll give an example - let's say we have a header file called common.h and 2 source files called src1.c and src2.c.
common.h
//lots of common function declarations implemented in some file common.c
int func(int a, int b);
src1.c
#include "common.h"
int func(int a, int b)
{
return a+b;
}
src2.c
#include "common.h"
int func(int a, int b)
{
return a*b;
}
let's say that I want each of the source file to use its local version of func(). is it possible to do so?
Yes, but if you attempted to link your main program against both src1 and src2 you would encounter an error because it wouldn't know which definition to use.
Headers are just ways for other code objects to be aware of what's available in other objects. Think of headers as a contract. Contracts are expected to be filled exactly one time, not zero or multiple times. If you link against both src1 and src2, you've essentially filled the int func(int a, int b); contract twice.
If you need to alternate between two functions with the same signature, you can use function pointers.
If you want each source file to only use its local implementation of func, and no other module uses those functions, you can remove the declaration from the header and declare them as static.
src1.c
static int func(int a, int b)
{
return a+b;
}
src2.c
static int func(int a, int b)
{
return a*b;
}
By doing this, each of these functions is only visible in the module it is defined in.
EDIT:
If you want two or more functions to implement an interface, you need to give them different names but you can use a function pointer to choose the one you want.
common.h
typedef int (*ftype)(int, int);
int func_add(int a, int b);
int func_mult(int a, int b);
src1.c
#include "common.h"
int func_add(int a, int b)
{
return a+b;
}
src2.c
#include "common.h"
int func_mult(int a, int b)
{
return a*b;
}
Then you can chose one or the other:
ftype func;
if (op=='+') {
func = func_add;
} else if (op=='*') {
func = func_mult;
...
}
int result = func(value1,value2);
If you compile it with each src[x].c, you'll be able to use it in any function of your .c
You can decide to not expose the function implementation to other translation units. In c, use keyword static before the function signature right where you implement the function (see code below); In C++, you can also use unnamed namespaces. By doing so, the linker will not give you an error, and each translation unit will use it's own implementation:
Suppose the following two translation units main.c and another.c. Both have their (private) implementation of int function(a,b), such that they yield different results when calling it:
extern void someOtherFeature();
static int function (a,b) {
return a+b;
}
int main(){
int x = function(1,2);
printf("main: function(1,2)=%d\n", x);
someOtherFeature();
}
// another.c:
#include <stdio.h>
static int function (a,b) {
return a*b;
}
void someOtherFeature() {
int x = function(1,2);
printf("someOtherFeature: function(1,2)=%d\n", x);
}
Output:
main: function(1,2)=3
someOtherFeature: function(1,2)=2
However, if both translation units exposed their implementations (i.e. both omitted keyword static, then the linker would report an error like duplicate symbol _function in:....
If you want each source file to use a local version of func, just put it in an unnamed namespace:
For example src1.C:
namespace
{
int func(int a, int b)
{
return a+b;
}
}
Then each source file will use its own version. You don't need to declare it in the header.
Note that your original code with the definitions at global namespace and declared in the header violates the one definition rule (two function definitions for the same name must always have the same definition), invoking undefined behavior, no diagnostic required.

Function Overloading in Visual c++

I was writing a program of function overloading in Visual C++ 2010 .
Following is my code
// overload.cpp : Defines the entry point for the console application.
#include<Windows.h>
#include<iostream>
#include<conio.h>
using namespace std;
//abs is overloaded in 3 types
int abs(int i);
double abs(double d);
long abs(long f);
void main()
{
cout<<abs(-10)<<"\n";
cout<<abs(-11.0)<<"\n";
cout<<abs(-9L)<<"\n";
getch();
}
int abs(int i)
{
cout<<"using integer abs()\n";
return i>0? -i:i;
}
double abs(double d)
{
cout<<"using double abs()\n";
return d>0? -d:d;
}
long abs (long l)
{
cout<<"using long abs()\n";
return l>0?-l:l;
}
I am having problems in double abs and long abs function that
1>c:\users\abc\documents\visual studio 2010\projects\overload\overload\overload.cpp(22): error C2084: function 'double abs(double)' already has a body
1>c:\users\abc\documents\visual studio 2010\projects\overload\overload\overload.cpp(26): error C2084: function 'long abs(long)' already has a body
Why this problem is coming?
I have changed the compilation from c to c++
but recently I ran an other program for overloading,it worked.I don't know how? here is the code.
#include<iostream>
#include<cstdio>
#include<conio.h>
#include<cstring>
using namespace std;
void stradd(char*s1,char*s2);
void stradd(char*s1,int i);
void main()
{
char str[80];
strcpy(str,"hello");
stradd(str,"there");
cout<<str<<"\n";
getch();
}
//concatenate a string with a "stringized "integer
void stradd(char*s1,int i)
{
char temp[80];
sprintf(temp,"%d",i);
strcat(s1,temp);
}
//concatenate 2 strings
void stradd(char*s1,char *s2)
{
strcat(s1,s2);
}
and output is hellothere
Your problem comes from a header in which abs is declared for some types such as double. You're not allowed to have to functions with exactly the same header (that is, same return type, same name, same list of parameters, same qualifiers such as const).
There are two ways of avoiding this:
Use the standard library: std::abs is good, you don't need to implement it yourself
Naming the method absoluteValue or myAbs or whatever you like, but not abs
A third way, namely removing using namespace std does not work according to your comment. This is because you include Windows.h. This itself includes a bunch of headers, probably including math.h. This gives a method called abs in the global namespace. Better don't include Windows.h and include cmath if you need to. Then, abs is only declared in namespace std, hence you can call it with std::abs and is different from abs.
When overload resolution cannot select one function as the unique best match, the call is ambiguous. An ambiguous call produces a compilation error.
In std there is already an abs() with the following signature:
int abs (int n);
So while you try to overload it with double and long it results in ambiguity for the compiler.
If you're a beginner learning about coding i suggest you to use function names not defined in libraries (at least the ones you have included).
stefan have already given the solution to it:
Remove using namespace std; and explicitly write std::cout
OR
Re name your function to absoluteValue or something else
OR
Use explicit namespaces in function declaration and calls. (Not tested, though it should work)
Put your function inside a class or namespace.
Maybe this would provide you with a little insight (From SO).
EDIT:
The second question's overloaded functions stradd() is not defined in any other library. That is why no Compilation Errors. The following function signature in your code will result an error: char * strcat ( char * destination, const char * source )
Your primary problem is that you use global namespace. Just declare your function in your own namespace and all name collisions will be gone.
Let me explain why you're getting those compile-time errors.
Somewhere in the headers you included there are double abs(double) and long abs(long) functions. Then you're creating functions with the same signatures by your own. So compiler just don't know what to use when you'll call one of them - there are 2 pairs of equal functions. So it refuses to compile that, and you're getting those errors.
So you have 2 choices - hope that every time you'll want to create a function you will choose an unique name, or just create a namespace and your function names should be unique only to another functions in your namespace.
And it's not about overloading - void func(int i) overloads void func(float f), but void func(int i) overrides void func(int i). You can override superclass member functions in subclasses, but you cannot override standalone functions like abs().
just change abs function name with another.
abs() is a keyword therefore it is showing errors.

Why does the compiler accept an ambiguous variables definitions?

I have such pretty little code:
//example1
namespace
{
int a;
}
int a;
main()
{
a++;
return 0;
}
Of course, g++ 4.6.1 compiler can't compile it and outputs an error:
./temp.cpp: In function ‘int main()’:
./temp.cpp:10:5: error: reference to ‘a’ is ambiguous
./temp.cpp:6:5: error: candidates are: int a
./temp.cpp:2:9: error: int {anonymous}::a
It's all right!
But when I delete the reference to variable "a" within "main" function, the program is being compiled well:
//example2
namespace
{
int a;
}
int a;
main()
{
return 0;
}
1) Why does the g++ compiler allows the definition of variable "a", when in such case it disallows the references to it?
2) Is it just the g++ compiler's feature, and no other compiler is able to compile such code (example2)?
3) Does the g++ compiler have corresponding flags to interpret such code (example2) as faulty?
Thanks a lot for everyone!
The second example is valid because you can still access the global a from outside that translation unit.
The a in the anonymous namespace provides a definition for a variable that has internal linkage. The a at global namespace scope is a definition for a variable with external linkage. You can declare a extern int a; in a different translation unit and use it.
Just because you can't reference the a in the anonymous namespace from main doesn't mean the code is invalid.
The a in the anonymous namespace can still be referenced from within the anonymous namespace.
The global a can be referenced from everywhere (you'd have to use ::a in main to remove the ambiguity).
The short answer is "because there's nothing illegal about it". It's just using a in main that is wrong. If you use ::a it will give you the global one (without the namespace).
And you can use a inside the namespace itself, e.g. we could have a function:
namespace {
int a;
int work_with_a()
{
a += 2;
return a;
}
}
int a;
int main()
{
::a++;
int b = work_with_a();
cout << ::a + b;
}

Exception Handling C++ error

#include<iostream>
#include<stdlib.h>
#include<string.h>
using namespace std;
class div
{
int x,y;
public:
class dividebyzero
{
};
class noerror1
{
};
div(){};
div(int a,int b)
{
x=a;
y=b;
}
void error1()
{
if(y==0)
throw dividebyzero();
else
throw noerror1();
}
int divide()
{
return (x/y);
}
};
class naming
{
char name[32];
public:
class nullexception
{
};
class noerror2
{
};
naming(char a[32])
{
strcpy(name,a);
}
void error2()
{
if(strcmp(name,"")==0)
throw nullexception();
else
throw noerror2();
}
void print()
{
cout<<"Name-----"<<name<<endl;
}
};
int main()
{
div d(12,0);
try
{
d.error1();
}
catch(div::dividebyzero)
{
cout<<"\nDivision by Zero-------Not Possible\n";
}
catch(div::noerror1)
{
cout<<"\nResult="<<d.divide()<<endl;
}
naming s("Pankaj");
try
{
s.error2();
}
catch(naming::nullexception)
{
cout<<"\nNull Value in name\n";
}
catch(naming::noerror2)
{
s.print();
}
return 0;
}
On compiling this program I am getting following error
pllab55.cpp: In function ‘int main()’:
pllab55.cpp:61:6: error: expected ‘;’ before ‘d’
pllab55.cpp:64:3: error: ‘d’ was not declared in this scope
pllab55.cpp:72:22: error: ‘d’ was not declared in this scope
pllab55.cpp:74:20: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
Before declaring the class naming everything was running fine.It is after declaration of naming these error started to occur. I am new to C++. Please explain me in details. Thanks in advance.
There is already an std::div in the standard namespace and since you use a using namespace directive instead of declaration it imports all the symbols in std namespace to your current scope. So perhaps renaming the div class shall do the trick for you.
I tried renaming it and it does work indeed.
So either rename your class or wrap it in your own namespace so it does not conflict with std::div
Your class div shares the same name as std::div. When you do #using namespace std, the result is that each class in the std namespace is imported into your current scope, meaning that std::div is now essentially called div. If you see, that means you now have two classes called div in the same scope, your own and the std class.
By the way, you should avoid the using namespace syntax and rather use the full qualifier of the class (e.g. std::cout).
Your div class is conflicting with std::div so either rename yours or put put your div class in a different namespace.
namespace me {
struct div{};
}
me::div d;
I gave (a slight variant of) your code a try in gcc and I got the following error:
/usr/include/stdlib.h:780: error: too few arguments to function 'div_t div(int, int)'
You're trying to override a name from a standard library and experience the conflict of a class and a function having the same name, I'm afraid.
as a general rule of thumb, if you encounter such issues, try to reduce your code as much as possible. For instance, I reduced it down to
#include<stdlib.h>
class div {
public:
div (int a, int b) { }
};
int
main () {
div d (12, 0);
return 0;
}
which still shows your error (at least the first one - the others are followup errors).
This lets you also reduce possible assumptions about the reason for the error - as you see, your new class "naming" does not have to do anything with the error you see.
When I now additionally remove the include, the error does not show up anymore, which lets me suspect some naming clash with some symbol from stdlib.h. After renaming the class "div" to something else (like "CDiv"), it works.

What are the complete legal entities that can be put in a namespace?

I'm learning C++ now. What are the complete legal entities that can be put in a namespace?
Legal entities here means valid members of a namespace
Oh, this is a real question. I'm coming from .net and I have the .net mindset.
Any code can be put inside namespace.
However main() function must be at global namespace. It cannot be put inside user-defined namespace.
namespace userns
{
int main()
{
return 0;
}
}
This program wouldn't compile link : http://www.ideone.com/k6SPc
Its because userns::main() will not be considered entry-point of the program; it became just like any other user function, not the standard main(). To compile it successfull, you've to add main() at global namespace:
namespace userns
{
int main()
{
return 0;
}
}
int main()
{
return 0;
}
This will compile link now : http://www.ideone.com/76Ynu
Anything can be put in a namespace (which is legal for C++, of course).
Actually, everything is in some namespace - the global namespace, if not specified.
Everything can be put in namespace except few "entities", which will not compile.
(1) Globally overloaded operator new and operator delete
namespace N
{
void* operator new (size_t size) // error
{ ... }
}
(2) Definition of the constructs which are declared in outer scope of the namespace; for example you have a class A declared globally then you cannot define its method inside your namespace N. In the same way, if you have method declared in a namespace N then you cannot put its definition inside namespace N::Nested (i.e. Nested is a namespace inside N).
//file
struct A {
void foo ();
static int i;
};
namespace N
{
int A::i = 0; // error
void A::foo() // error
{}
}
Demo: this is not allowed.
I remember at least these 2 restrictions from my experience. Don't know about specs.