Confused in output of a program - c++

I'm new to c++ and i'm practicing about class. kindly someone help me with this. What's the error?
class Test1 {
int y;
};
class Test2 {
int x;
Test1 t1;
public:
operator Test1() { return t1; }
operator int() { return x; }
};
void fun ( int x) { };
void fun ( Test1 t ) { };
int main() {
Test2 t;
fun(t);
return 0;
}

When compiling :
t.cc: In function ‘int main()’:
t.cc:18:10: error: call of overloaded ‘fun(Test2&)’ is ambiguous
fun(t);
^
t.cc:13:6: note: candidate: void fun(int)
void fun ( int x) { }
^~~
t.cc:14:6: note: candidate: void fun(Test1)
void fun ( Test1 t ) { }
^~~
To solve that you have to indicate your choice :
fun(static_cast<Test1>(t));
or
fun(static_cast<int>(t));
or of course to remove one of the conversion operator

It's a Compiler Error.
There are two conversion operators defined in the Test2 class. So Test2 objects can automatically be converted to both int and Test1. Therefore, the function call fun(t) is ambiguous as there are two functions void fun(int ) and void fun(Test1 ), compiler has no way to decide which function to call. In general, conversion operators must be overloaded carefully as they may lead to ambiguity.

Related

Why is this overloaded std::function parameter ambiguous?

I have the below code, where a class is trying to take one of two std::function signatures through its constructor. I'm able to get the signature that has the double parameter to compile, but the parameter-less signature fails to compile, saying the call is ambiguous.
#include <functional>
class Foo
{
public:
void baz(double value) {
}
};
class Bar
{
public:
void baz() {
}
};
class Overloader {
public:
Overloader(std::function<void(double)> inFuncWithArg)
: funcWithArg(inFuncWithArg)
{
}
Overloader(std::function<void(void)> inFuncNoArg)
: funcNoArg(inFuncNoArg)
{
}
private:
std::function<void(double)> funcWithArg;
std::function<void(void)> funcNoArg;
};
int main()
{
Foo foo;
Bar bar;
// Compiles
Overloader overloader1(std::bind(static_cast<void(Foo::*)(double)>(&Foo::baz)
, &foo, std::placeholders::_1));
// Fails to compile - "call of overloaded ‘Overloader(std::_Bind_helper::type)’ is ambiguous"
Overloader overloader2(std::bind(static_cast<void(Bar::*)(void)>(&Bar::baz)
, &bar));
return 0;
}
What am I missing that's causing this to fail? Also, are there any less-verbose ways to do this?
Here's the full error output
main.cpp: In function ‘int main()’:
main.cpp:51:20: error: call of overloaded ‘Overloader(std::_Bind_helper::type)’ is ambiguous
, &bar));
^
main.cpp:32:5: note: candidate: Overloader::Overloader(std::function)
Overloader(std::function<void(void)> inFuncNoArg)
^~~~~~~~~~
main.cpp:27:5: note: candidate: Overloader::Overloader(std::function)
Overloader(std::function<void(double)> inFuncWithArg)
^~~~~~~~~~
This question is more about std::bind than std::function.
The result of the expression
std::bind(&Foo::baz, &foo, std::placeholders::_1)
is invocable with one or more arguments, where the first argument is convertible to double.
The result of the expression
std::bind(&Bar::baz, &bar)
is invocable with zero or more arguments, with no restrictions.
The first expression can thus only initialize std::function<void(double)>, but the second expression can initialize either std::function<void(double)> or std::function<void(void)> and is ambiguous.
Genuinely, do not use std::bind. You can use std::bind_front if you have it. Alternatively, use a lambda.
std::bind_front:
std::bind_front(&Foo::baz, &foo)
std::bind_front(&Bar::baz, &bar)
lambda:
[&foo](double) { foo.baz(value); }
[&bar] { bar.baz(); }
Just use a lambda:
auto overloader1 = [&foo](double value) { foo.baz(value); };
auto overloader2 = [&bar]() { bar.baz(); }

operator overloading and function overloading producing ambiguous compiler error

In the given code, I am not able to understand why the compiler is producing errors when the function is called. It is passing object of test class which has its data member of a test2 class
class Test2 {
int y;
};
class Test {
int x;
Test2 t2;
public:
operator Test2 () {return t2;}
operator int () {return x;}
};
void fun (int x) {
cout << "fun(int) called";
}
void fun (Test2 t) {
cout << "fun(Test 2) called";
}
int main() {
Test t;
fun(t);
return 0;
}
I am not able to understand why the compiler is producing errors when the function is called
How is the compiler supposed to figure out which function to call? You have two function in the overload set associated with the name func, and two operators that allow for implicit conversions to types that equally well match both function parameters of this overload set.
The situation is identical to
void f(long);
void f(short);
f(42); // Error: both conversions int -> log and int -> short possible
You can fix it by e.g.
fun(static_cast<Test2>(t)); // be explicit on the calling side
or by marking one (or both) of the conversion operators as explicit
explicit operator Test2 () {return t2;}
which disables implicit conversions to Test2 and requires an explicit cast as shown before.
The call fun(t); is ambiguous because both overloads of fun are eligible for it.
This is again because t is a Test object which can be converted to both Test2 and int.
Marking either one of the conversion operators as explicit will resolve this issue.
See Demo here.

C++ class copy constructor has no matching function

I am trying to write a class Core, it's member variable is a pointer. The copy constructor is Core(Core& x) instead of Core(const Core& x).
Core has a member function Core Core::new_core (int * ptr), the code has a problem when I try to construct Core new_core= core.new_core(ptr);, please see the code and error information below.
#include<iostream>
class Core
{
private:
int* a;
public:
Core(int* in) {a=in;}
Core(Core& x) {a = x.data();}
inline const int * data() const {return a;}
inline int * data() {return a;}
Core new_core (int * ptr)
{
Core b(ptr);
return b;
}
};
using namespace std;
int main()
{
int ptr[3]= {1,2,3};
Core core(ptr);
Core new_core= core.new_core(ptr);
cout<< new_core.data() <<endl;
return 0;
}
Error information:
main.cpp: In function ‘int main()’:
main.cpp:30:37: error: no matching function for call to ‘Core::Core(Core)’
Core new_core= core.new_core(ptr);
^
main.cpp:30:37: note: candidates are:
main.cpp:12:6: note: Core::Core(Core&)
Core(Core& x) { a = x.data() ;}
^
main.cpp:12:6: note: no known conversion for argument 1 from ‘Core’ to >‘Core&’
main.cpp:10:6: note: Core::Core(int*)
Core(int* in) {a=in;}
^
main.cpp:10:6: note: no known conversion for argument 1 from ‘Core’ to
‘int*’
I can easily fix the problem by replacing
Core(Core& x) { a = x.data() ;}
to
Core(const Core& x) { a = const_cast<int* > ( x.data() ) ;},
is there a better way to solve the problem without using const_cast?
I want to keep int* a private, and keep following two lines:
inline const int * data() const {return a;}
inline int * data() {return a;}
Thank you.
The problem here is that new_core returns a Core which is a temporary. When you use it in
Core new_core= core.new_core(ptr);
The compiler calls the copy constructor but it cannot bind to that temporary since it takes a reference. To fix this we can change the copy constructor to take a const Core& which can bind to the temporary and allow you to make a copy.
In this example to get around the const and the use ofconst_cast we can access the class member directly like:
Core(const Core& x) : a(x.a) {}

C++: Weird behavior on method overloading

I need explanation about why the following code does not compile. I have a workaround which I will articulate below, but I don't understand the failure of the original version.
To speed up code reading: The concept is to define an interface (ISomething), then to create an abstract implementation (ASomething) which implements the second function (2) using the first (not yet defined) one (1). A complete implementation which derives from the abstract one (for example SomethingImpl) must define the first method and has the option to override the second one.
#include <iostream>
class ISomething
{
public:
virtual ~ISomething()
{ }
virtual int f(int x) = 0; // (1)
virtual int f(int x, int y) = 0; // (2)
};
class ASomething
: public virtual ISomething
{
public:
virtual int f(int x, int y) // (2)
{
return f(x) + f(y); // (3)
}
};
class SomethingImpl
: public ASomething
{
public:
virtual int f(int x) // (1)
{
return x+1;
}
};
int main()
{
SomethingImpl a;
std::cout << a.f(10) << std::endl; // (1)
std::cout << a.f(10,20) << std::endl; // (2)
return 0;
}
Compiling this code gives error on both Visual Studio 2013 (Windows) and g++ 4.4.5 (Linux). The errors are very similar, I will detail the g++ output only:
$ g++ SibFun.cpp -o SibFun
SibFun.cpp: In member function ‘virtual int ASomething::f(int, int)’:
SibFun.cpp:18: error: no matching function for call to ‘ASomething::f(int&)’
SibFun.cpp:16: note: candidates are: virtual int ASomething::f(int, int)
SibFun.cpp:18: error: no matching function for call to ‘ASomething::f(int&)’
SibFun.cpp:16: note: candidates are: virtual int ASomething::f(int, int)
SibFun.cpp: In function ‘int main()’:
SibFun.cpp:36: error: no matching function for call to ‘SomethingImpl::f(int, int)’
SibFun.cpp:26: note: candidates are: virtual int SomethingImpl::f(int)
make: *** [SibFun] Error 1
I tried to use different notation at (3) like return this->f(x) + this->f(y), but I experienced no significant change in the error message.
However when I changed (3) to return ISomething::f(x) + ISomething::f(y); I only got:
$ g++ SibFun.cpp -o SibFun
SibFun.cpp: In function ‘int main()’:
SibFun.cpp:36: error: no matching function for call to ‘SomethingImpl::f(int, int)’
SibFun.cpp:26: note: candidates are: virtual int SomethingImpl::f(int)
make: *** [SibFun] Error 1
But! When change (2) from f to g all compiles and runs as expected.
What is the reason behind this begavior? Why can't I use the f name for (2)?
Function overloading works only for functions visible in the same scope:
class ASomething
: public virtual ISomething
{
public:
virtual int f(int x, int y) // (2)
{
return f(x) + f(y); // (3)
}
using ISomething::f;
//~~~~~~~~~~~~~~~~~^
};
class SomethingImpl
: public ASomething
{
public:
virtual int f(int x) // (1)
{
return x+1;
}
using ASomething::f;
//~~~~~~~~~~~~~~~~~^
};
Both compilation failures happen for the same reason. While you're overriding one virtual member function, you're hiding the other. In ASomething:
virtual int f(int x, int y) // (2)
{
return f(x) + f(y); // (3)
}
Name lookup on f finds ASomething::f and stops, it doesn't keep going to look for other overloads. Since ASomething::f takes two arguments, and you're trying to call it with one, error. In order to allow for overloading against the base class, you have to introduce the base class member functions with a using-declaration:
using ISomething::f; // NOW, ISomething::f(int ) is found by lookup
virtual int f(int x, int y)
{
return f(x) + f(y);
}
And similarly, SomethingImpl needs a using ASomething::f; statement so that a.f(10) can compile.
The problem is not an 'overloading' problem, but hiding a base class function (See other answers)
A slightly modified example:
#include <iostream>
class ISomething
{
public:
virtual ~ISomething() {}
virtual int f(int x) = 0; // (1)
virtual int f(int x, int y) = 0; // (2)
};
class ASomething: public virtual ISomething
{
public:
virtual int f(int x, int y) // (2)
{
// `this->f(x)` fails:
ISomething& i = *this;
return i.f(x) + i.f(y); // (3)
}
};
class SomethingImpl: public ASomething
{
public:
virtual int f(int x) // (1)
{
return x+1;
}
};
int main()
{
SomethingImpl a;
// `a.f(10, 20)` fails:
ISomething& i = a;
std::cout << i.f(10) << std::endl; // (1)
std::cout << i.f(10, 20) << std::endl; // (2)
return 0;
}
Hence, calling f from the interface, resolves the conflict. Although, you should consider using base::f, as suggested in other answers.

Is this function overloading correct?

Consider having these four functions in one C++ program:
void a(int val)
{
cout<<val;
}
void a(int &val)
{
cout<<val;
}
void a(int *val)
{
cout<<val;
}
void a(double val)
{
cout<<val;
}
Few Questions i have are:
Is there going to be any error in the code? or are they all overloaded without any error.
Can you tell me how to call all of these four functions correctly? My try was below:
int iTmp;
int *pTmp;
double dTmp;
a(iTmp);
a(iTmp);
a(pTmp);
a(dTmp);
The only problem are the functions:
void a(int &val)
and
void a(int val)
The compiler will create the following errors:
Compilation error time: 0 memory: 3140 signal:0
prog.cpp: In function 'int main()':
prog.cpp:28:8: error: call of overloaded 'a(int&)' is ambiguous
a(iTmp);
^
Because he cant distinguish both, if you remove one of them the compilation succeeds
See Example:
#include <iostream>
using namespace std;
void a(int val)
{
cout<<val;
}
void a(int *val)
{
cout<<val;
}
void a(double val)
{
cout<<val;
}
int main() {
int iTmp = 0;
int *pTmp = 0;
double dTmp = 0.0;
a(iTmp);
a(iTmp);
a(pTmp);
a(dTmp);
return 0;
}
See working example:
http://ideone.com/WRZUoW
Your code will compile but calling
int iTmp;
a(iTmp);
will yield an ambiguous overload resolution call since both
void a(int val)
{
cout<<val;
}
void a(int &val)
{
cout<<val;
}
will match.
The reason for this lies in the standard:
[over.match.best]
A viable function F1 is defined to be a better function than another viable function F2 if for all arguments i, ICSi(F1) is not a worse conversion sequence than ICSi(F2)
int->int
int->int&
these are standard conversion sequences and the entire list of [over.ics.rank]p3.2 is checked without success for a better conversion sequence (exact match in both cases)
They are thus deemed "undistinguishable".
A word of advice: the variable are also not initialized and (if automatic variables) even if your code compiled, the output would be undefined.
The compiler must be able to know what function to call.
With
int i = 12;
a(i);
both a(int i) and c(int& i) are acceptable candidates and compiler throws an error.
and
void a(const int& i) { ... }
will suffer from same problem.
These two function will cause issues
void a(int val)
{
cout<<val;
}
void a(int &val)
{
cout<<val;
}
Your call a(iTmp); have two possible candidates. Compiler should shown an error for these. Otherwise pointer argument(int *val)and double argument(double val) are okay.
The most obvious problem is that
void a(int val) {
and
void a(int& val) {
are ambiguous when called with iTmp.
Aside from that, depending on whether the variables are global or local ones, the code is using uninitialized variables -> UB and whether or not,
void a(int* val) {
std::cout << val << std::endl;
}
is overloaded correctly is up for debate. I'd assume that it should be std::cout << *val << std::endl;, but that of course depends on what the function is supposed to do (although a function that prints an address would usually be parameterized by (void* or char*);