void f(const string& a,const string& b){
// works
int lena = a.length();
int lenb = b.length();
return abs(lena-lenb);
// does not work
return abs(a.length()-b.length());
}
I'm in a little confusion I'm not able call string length() function in abs() function. When I put the result of string length() function in an integer data type there is no error.
The error is this when I call string length() function inside abs().
error: call of overloaded
abs(std::__cxx11::basic_string<char>::size_type) is ambiguous
abs(a.length()-b.length);
When you write:
a.length()-b.length()
The result ends up having type std::size_t because the return type of std::string::length() is std::size_t too.
When you call std::abs with such a type, the compiler has to choose one of the following overloads:
int abs(int n);
long abs(long n);
long long abs(long long n);
std::intmax_t abs(std::intmax_t n);
And there is no rule in the language that promotes/converts an unsigned integer to a specific signed one here, which means the compiler cannot choose for you.
However, when you call it with:
lena-lenb
That has type int since it is the subtraction of two ints, so the following overload is chosen:
int abs(int n);
Related
I'm defining a function signature in order to perform a remote procedure call. Due to undefined behavior, I cannot increment the index variable in the call expression so I ended up counting from 0 to the last index and passed each to the function as argument. Is there a more elegant way to accomplish this without counting? I was thinking about a loop or something. This would come in handy when the fixed arguments count changes to e.g. 16 arguments instead of 8.
typedef unsigned long long int functionType(int, int, int, int, int, int, int, int);
unsigned long long int call_address(uintptr_t real_address, const unsigned int *arguments) {
auto function = (functionType *) real_address;
// We count instead of incrementing an index variable because: operation on 'argumentIndex' may be undefined
return function(arguments[0], arguments[1],
arguments[2], arguments[3],
arguments[4], arguments[5],
arguments[6], arguments[7]);
}
I know there are variable arguments using va_start, va_list and va_end but I'm not sure if they can be used here.
A part of your solution involves unpacking a fixed amount of values from your arguments array and calling function with it. The following C++14 code will do that:
template <typename F, size_t... Is>
unsigned long long int our_invoke(F f, const unsigned int * args, std::index_sequence<Is...>) {
return f(args[Is]...);
}
unsigned long long int call_address(uintptr_t real_address, const unsigned int *arguments) {
auto function = (functionType *) real_address;
return our_invoke(function, arguments, std::make_index_sequence<8>{});
}
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.
void qsort (void* base, size_t num, size_t size,
int (*compare)(const void*,const void*));
Why does the qsort function want an int* return type for compare when the compare function is of type int?
int compare (const void * a, const void * b)
{
if ( *(MyType*)a < *(MyType*)b ) return -1;
if ( *(MyType*)a == *(MyType*)b ) return 0;
if ( *(MyType*)a > *(MyType*)b ) return 1;
}
Can someone explain this please, my program wont compile because of this. Thanks!
Code taken from this source:
http://www.cplusplus.com/reference/cstdlib/qsort/
It is not returning an int *, it is returning an int. compare is a function pointer. The * you are seeing there defines it as a function pointer. (Note the parentheses around *compare.)
cdecl parse of int (*compare)(const void*,const void*)):
declare compare as pointer to function (pointer to const void, pointer to const void) returning int
This would be the parameter declaration if it were a pointer to a function returning an int *:
int * (*compare)(const void*,const void*))
If your code is not compiling then it is for some other reason. Consider adding the error message to your question (or creating a new question) if you would like more specific advice about the compiler error.
I'm using a template to convert integral types into a string representation of their binary values. I used the following:
template<typename T>
std::string ToBinary(const T& value)
{
const std::bitset<std::numeric_limits<T>::digits + 1> bs(value);
const std::string s(bs.to_string());
return s;
}
It works for int but doesn't compile with unsigned int :
unsigned int buffer_u[10];
int buffer_i[10];
...
ToBinary(buffer_i[1]); //compile and works
ToBinary(buffer_u[1]); //doesn't compile -- ambiguous overload
Could you explain why?
EDIT:
Yes, I'm using VS2010
Not your ToBinary call is ambiguous, its the constructor call of bitset with an unsigned value. Unfortunately this is a VC++ Bug: http://connect.microsoft.com/VisualStudio/feedback/details/532897/problems-constructing-a-bitset-from-an-unsigned-long-in-the-vc-rc
Edit - Workaround:
template<>
std::string ToBinary<unsigned int>(const unsigned int& value)
{
const std::bitset<std::numeric_limits<unsigned int>::digits> bs(static_cast<unsigned long long>(value));
return bs.to_string();
}
If you look at the standard (FDIS n3290), then you see that std::bitset has multiple constructors:
First there is this one:
20.5.1 bitset constructors [bitset.cons]
constexpr bitset(unsigned long long val) noexcept;
Effects: Constructs an object of class bitset, initializing the
first M bit positions to the corresponding bit values in val. M is the
smaller of N and the number of bits in the value representation (3.9)
of unsigned long long. If M < N, the remaining bit positions are
initialized to zero.
Then there is also this one, which I suspect might be might cause things to become ambigious, when you call it with unsigned int
template <class charT>
explicit bitset(
const charT* str,
typename basic_string<charT>::size_type n = basic_string<charT>::npos,
charT zero = charT(’0’), charT one = charT(’1’));
Effects: Constructs an object of class bitset as if by
bitset( n == basic_string<charT>::npos ? basic_string<charT>(str) :
basic_string<charT>(str, n), 0, n, zero, one)
Are you using VC10? There is already an issue reported: Microsoft connect. Also I'd guess that you might be able to fix it by casting the type to int if it is 32 bit, like this:
string s = ToBinary(*reinterpret_cast<int*>(&buffer_u[1]));
This can be done inside of the method as well if needed. The result of the reinterpret should not be used for arithmetics anymore, though. ;)
Works fine as workaround for me (but looks quite ugly)
template<typename T>
std::string ToBinary(const T& value)
{
switch (sizeof(T))
{
case 8:
return std::bitset<std::numeric_limits<T>::digits + 1>(*reinterpret_cast<const long*>(&value)).to_string();
case 4:
return std::bitset<std::numeric_limits<T>::digits + 1>(*reinterpret_cast<const int*>(&value)).to_string();
case 2:
return std::bitset<std::numeric_limits<T>::digits + 1>(*reinterpret_cast<const short*>(&value)).to_string();
case 1:
return std::bitset<std::numeric_limits<T>::digits + 1>(*reinterpret_cast<const char*>(&value)).to_string();
}
return "n/a";
}
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.