Call of overloaded function is ambiguous - c++

What does this error message mean?
error: call of overloaded ‘setval(int)’ is ambiguous
huge.cpp:18: note: candidates are: void huge::setval(unsigned int)
huge.cpp:28: note: void huge::setval(const char*)
My code looks like this:
#include <iostream>
#define BYTES 8
using namespace std ;
class huge {
private:
unsigned char data[BYTES];
public:
void setval(unsigned int);
void setval(const char *);
};
void huge::setval(unsigned int t) {
for(int i = 0; i< BYTES ; i++) {
data[i] = t;
t = t >> 1;
}
}
void huge::setval(const char *s) {
for(int i = 0; i< BYTES ; i++)
data[i] = s[i];
}
int main() {
huge p;
p.setval(0);
return 0;
}

The literal 0 has two meanings in C++.
On the one hand, it is an integer with the value 0.
On the other hand, it is a null-pointer constant.
As your setval function can accept either an int or a char*, the compiler can not decide which overload you meant.
The easiest solution is to just cast the 0 to the right type.
Another option is to ensure the int overload is preferred, for example by making the other one a template:
class huge
{
private:
unsigned char data[BYTES];
public:
void setval(unsigned int);
template <class T> void setval(const T *); // not implemented
template <> void setval(const char*);
};

The solution is very simple if we consider the type of the constant value, which should be "unsigned int" instead of "int".
Instead of:
setval(0)
Use:
setval(0u)
The suffix "u" tell the compiler this is a unsigned integer. Then, no conversion would be needed, and the call will be unambiguous.

replace p.setval(0); with the following.
const unsigned int param = 0;
p.setval(param);
That way it knows for sure which type the constant 0 is.

Use
p.setval(static_cast<const char *>(0));
or
p.setval(static_cast<unsigned int>(0));
As indicated by the error, the type of 0 is int. This can just as easily be cast to an unsigned int or a const char *. By making the cast manually, you are telling the compiler which overload you want.

Cast the value so the compiler knows which function to call:
p.setval(static_cast<const char *>( 0 ));
Note, that you have a segmentation fault in your code after you get it to compile (depending on which function you really wanted to call).

That is ambiguous because a pointer is just an address, so an int can also be treated as a pointer – 0 (an int) can be converted to unsigned int or char * equally easily.
The short answer is to call p.setval() with something that's unambiguously one of the types it's implemented for: unsigned int or char *. p.setval(0U), p.setval((unsigned int)0), and p.setval((char *)0) will all compile.
It's generally a good idea to stay out of this situation in the first place, though, by not defining overloaded functions with such similar types.

Related

How to pass a char as an argument of a function inside a class using template

I'm trying to pass a char array into a function(push) inside this class(BaseStack):
template < class T >
class BaseStack
{
void push(const T&item){
//Ignore
}
}
What I tried was:
char finalstring[L];
for(int i = 0 ; i < 5; i++)
finalstring[i] = 'x';
BaseStack<char> c;
c.push(finalstring);
But my compiler said that I was doing an invalid conversion
BaseStack<char> c;
This means that your template parameter is char. This is what you specified for the template parameter. Therefore, the instance of your template is, in so many words, and very loosely speaking:
class BaseStack
{
void push(const char &item){
//Ignore
}
}
This is what happens, since your template parameter is a char. T is char, and since the parameter in the template is void push(const T &item), then that's what you get.
c.push(finalstring);
finalstring is a char array, which decays to a char *. This attempts to pass a char * to a class method that takes a (const refence to a) char. This is not allowed in C++, and that's the reason for your compilation error.
It is unclear what your intent is here, whether the template parameter should be either a const T *, or you need to pass finalstring's first character, only. Doing either will solve this particular compilation error.

C vs. C++, handling of void** pointers

I found out that using a C compiler the code below works but not with a C++ compiler. I understand that casting to void** is the correct usage but I can't understand why it compiles with the C compiler even if I use the void* (commented out).
#include <stdio.h>
int fn(void **arg)
{
int *pvalue = *(int**)arg;
*pvalue = 200;
return 0;
}
int main()
{
int value = 99;
int *pvalue = &value;
// fn((void *)&pvalue); // works only in C
// error C2664: 'int fn(void **)': cannot convert argument 1 from 'void *' to 'void **'
fn((void **)&pvalue); // correct, works for both C/C++
printf("%d", value);
return 0;
}
Can someone explain why this is the case?
In C there is allowed to assign a pointer of the type void * to a pointer of other type. This takes place in this call
fn((void *)&pvalue)
where the argument has the type void * that is assigned to the function parameter that has the type void **.
int fn(void **arg)
{
int *pvalue = *(int**)arg;
*pvalue = 200;
return 0;
}
However such an assignment in general is unsafe. For example the value of a pointer of the type void * can not be properly aligned to be assigned to a pointer of other type.
So it was decided to not allow such an assignment in C++ to make programs more safer.
I can't understand why it compiles with the C compiler even if I use the void* (commented out).
It compiles because void* is implicitly convertible to other pointers in C.
fn((void **)&pvalue); // correct, works for both C/C++
This may be well-formed because of the cast, the standard doesn't technically give explicit guarantee that conversion to void** and back yields the same address.
While this may be likely to work in practice, there is no reason to not use void* as the function argument instead, which does have the guarantee. As a bonus, you won't need the cast in the call. Like this:
int fn(void *arg);
fn(&pvalue); // correct, works for both C/C++
Of course, this is assuming type erasure is needed in the first place. Avoid void* when it is not needed.
For avoidance of doubt, there is nothing correct in
fn((void **)&pvalue);
It is just as incorrect as
fn((void *)&pvalue);
The correct way to use the API is to do
int fn(void **arg)
{
int *pvalue = (int *)*arg;
*(int *)pvalue = 200;
return 0;
}
or
int fn(void **arg)
{
*(int *)*arg = 200;
return 0;
}
with
int main()
{
int value = 99;
void *pvalue = (void*)&value;
fn(&pvalue);
printf("%d", value);
return 0;
}
You're not allowed to access an object using any other pointer type, other than the declared type, compatible type, or a character type. Furthermore, while void * is used as a generic pointer type to all sorts of objects in C, there is no generic pointer to a pointer type in C - other than void *!
And this is the reason why the void ** is almost always a sign of a design error in APIs - most usages are just wrong.

Why am I getting cmath errors in terminal? [duplicate]

What does this error message mean?
error: call of overloaded ‘setval(int)’ is ambiguous
huge.cpp:18: note: candidates are: void huge::setval(unsigned int)
huge.cpp:28: note: void huge::setval(const char*)
My code looks like this:
#include <iostream>
#define BYTES 8
using namespace std ;
class huge {
private:
unsigned char data[BYTES];
public:
void setval(unsigned int);
void setval(const char *);
};
void huge::setval(unsigned int t) {
for(int i = 0; i< BYTES ; i++) {
data[i] = t;
t = t >> 1;
}
}
void huge::setval(const char *s) {
for(int i = 0; i< BYTES ; i++)
data[i] = s[i];
}
int main() {
huge p;
p.setval(0);
return 0;
}
The literal 0 has two meanings in C++.
On the one hand, it is an integer with the value 0.
On the other hand, it is a null-pointer constant.
As your setval function can accept either an int or a char*, the compiler can not decide which overload you meant.
The easiest solution is to just cast the 0 to the right type.
Another option is to ensure the int overload is preferred, for example by making the other one a template:
class huge
{
private:
unsigned char data[BYTES];
public:
void setval(unsigned int);
template <class T> void setval(const T *); // not implemented
template <> void setval(const char*);
};
The solution is very simple if we consider the type of the constant value, which should be "unsigned int" instead of "int".
Instead of:
setval(0)
Use:
setval(0u)
The suffix "u" tell the compiler this is a unsigned integer. Then, no conversion would be needed, and the call will be unambiguous.
replace p.setval(0); with the following.
const unsigned int param = 0;
p.setval(param);
That way it knows for sure which type the constant 0 is.
Use
p.setval(static_cast<const char *>(0));
or
p.setval(static_cast<unsigned int>(0));
As indicated by the error, the type of 0 is int. This can just as easily be cast to an unsigned int or a const char *. By making the cast manually, you are telling the compiler which overload you want.
Cast the value so the compiler knows which function to call:
p.setval(static_cast<const char *>( 0 ));
Note, that you have a segmentation fault in your code after you get it to compile (depending on which function you really wanted to call).
That is ambiguous because a pointer is just an address, so an int can also be treated as a pointer – 0 (an int) can be converted to unsigned int or char * equally easily.
The short answer is to call p.setval() with something that's unambiguously one of the types it's implemented for: unsigned int or char *. p.setval(0U), p.setval((unsigned int)0), and p.setval((char *)0) will all compile.
It's generally a good idea to stay out of this situation in the first place, though, by not defining overloaded functions with such similar types.

I can't use char in function

bool potezn(int x,int y,int k,char c,char ram1[][100],bool segfault,int n,int m)
{
segfault=true;
if(c=='U' && x>=k){x=x-k;segfault=false;}
if(c=='D' && x+k<n){x=x+k;segfault=false;}
if(c=='L' && y>=k){y=y-k;segfault=false;}
if(c=='R' && y+k<m){y=y+k;segfault=false;}
if(ram1[x][y]=='.')ram1[x][y]='N';//zauzima polozaj ukoliko moze
return segfault;
}
segfault=potezn(x,y,q,c,ram,segfault,n,m);
This is my code,and when i run it,i keep getting error
D:\dev\Dev-Cpp\segfault2.cpp
cannot convert char (*)[((unsigned int)((int)m))] to char (*)[100] for argument 5 to bool potezn(int, int, int, char, char (*)[100], bool, int, int)
Help please,
Thanks in advance
The reason you are getting that compile error is because the type of ram that you are trying to call the function potezn with is not the type potezn wants.
Take a careful look at ram.
Its type must be char*[100], not char(*)[((unsigned int)((int)m)]].
You can either declare ram's length explicitly, or change char ram1[][100] to char * ram1. (Also consider using std::vector. std::vector is an array that manages its length automatically for you.)
void Foo(char ram[][100]);
void Bar(char * ram); // Treat the ram as one long chunk array.
int main()
{
char ram[5][100];
char ram_error[5][5];
Foo(ram); // Ok.
Foo(ram_error); // Error.
Bar(reinterpret_cast<char *>(ram_error)); // Ok. Not recommended.
return 0;
}

operator function in C++ and compile error relating to it

there are probably several ways I will expose my ignorance with this question :)
First, I think this is C++ code, but the extension of the file is .C (so maybe it is C?)
Anyway, I am trying to compile a program called Sundance (Sentence UNDerstanding ANd Concept Extraction) which is a Natural Language Processing tool. The compile error I get relates to the following:
// This class is used internally to keep track of constituents that are
// potential subjects for clauses during clause handling.
class PotentialXP {
public:
Constituent* XPPtr;
unsigned int Distance;
unsigned int ClauseIndex;
unsigned int ConstIndex;
PotentialXP() {
XPPtr = 0;
Distance = 0;
ClauseIndex = 0;
ConstIndex = 0;
};
operator int() const {
return (int)XPPtr;
};
void Set(Constituent* w,
unsigned int x,
unsigned int y,
unsigned int z){
XPPtr = w;
Distance = x;
ClauseIndex = y;
ConstIndex = z;
};
};
The error is "cast from ‘Constituent* const*’ to ‘int’ loses precision"
and relates to the lines:
operator int() const {
return (int)XPPtr;
};
I understand why I get an error. XPPtr is of type Constituent*, so how can it be converted to an integer? Can anyone figure out what the author of the code wants to do here, and how I might rewrite this line so it compliles? What is an operator function (if that's what you call it) for?
Any advice much appreciated!
That compiles fine for me. You are on a 64-bit machine, where size_t is larger than int.
Explanation: you can historically convert a pointer an int
struct Foo {};
int main ()
{
Foo * f = new Foo ();
std :: cout << (int)f; // Prints 43252435 or whatever
}
If you want an integer which is the same size as a pointer, use size_t or ssize_t.
And why on earth are you writing operator int() like that anyway? Do you want operator bool() to test for validity? In which case a function body of return NULL != XPPtr would be better style -- clearer, at least.
The line operator int() const states a how your object can be cast to int.
The Constituent* can be cast to int because both types are usually the same size. I do not think that this is what the programmer intended, since the raw pointer value is of no semantic use. Maybe there should be a field lookup? E.g:
operator int() const {
return (int)XPPtr->somevalue;
};