How do I fix an "ambiguous" function call? - c++

I'm working on a C++ program for class, and my compiler is complaining about an "ambiguous" function call. I suspect that this is because there are several functions defined with different parameters.
How can I tell the compiler which one I want? Aside from a case-specific fix, is there a general rule, such as typecasting, which might solve these kinds of problems?
Edit:
In my case, I tried calling abs() inside of a cout statement, passing in two doubles.
cout << "Amount is:" << abs(amountOrdered-amountPaid);
Edit2:
I'm including these three headers:
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
Edit3:
I've finished the program without this code, but in the interest of following through with this question, I've reproduced the problem. The verbatim error is:
Call to 'abs' is ambiguous.
The compiler offers three versions of abs, each taking a different datatype as a parameter.

What's happened is that you've included <cstdlib> (indirectly, since it's included by iostream) along with using namespace std;. This header declares two functions in std with the name abs(). One takes and returns long long, and the other returns long. Plus, there's the one in the global namespace (that returns int) that comes from <stdlib.h>.
To fix: well, the abs() that takes double is in <cmath>, and that will actually give you the answer you want!

The abs function included by <cstdlib> is overloaded for int and long and long long. Since you give a double as the argument, the compiler does not have an exact fit, so it tries to convert the double to a type that abs accepts, but it does not know if it should try to convert it to int, long, or long long, hence it's ambiguous.
But you probably really want the abs that takes a double and returns a double. For this you need to include <cmath>. Since the double argument matches exactly, the compiler will not complain.
It seems that <cstdlib> gets included automatically when you include the other headers which should not happen. The compiler should have given error: ‘abs’ was not declared in this scope or something similar.

Try using fabs defined in <cmath>. It takes float, double and long double as arguments. abs is defined both in <cmath> and <cstdlib>. The difference is abs(int), abs(long) and abs(long long) are defined in <cstdlib> while other versions are defined in <cmath>.

Not sure why this isn't calling the int version of abs but you could try type casting the expression (amountOrdered - amountPaid) as int i.e.
cout <<"Amount is: "<< abs( (int)(amountOrdered - amountPaint) );

Related

Why can't I include the standard algorithm library after defining 'epsilon' in C++?

When I include the algorithm library before defining epsilon, the following code compiles:
#include <iostream>
#include <algorithm>
#define epsilon 0.00001
int main() {
std::cout << epsilon;
return 0;
}
When I switch them around, it doesn't:
#include <iostream>
#define epsilon 0.00001
#include <algorithm>
int main() {
std::cout << epsilon;
return 0;
}
It gives the following error 19 times:
epsilon_algorithm.cpp:3:17: error: expected unqualified-id before numeric constant
3 | #define epsilon 0.00001
|
On http://www.cplusplus.com/reference/algorithm/ and https://en.cppreference.com/w/cpp/algorithm there is no mention of anything named 'epsilon'. I know I can avoid the issue by simply always including <algorithm> before I define epsilon, I want to know what causes this error to broaden my understanding of C++ and prevent these types of errors in the future.
I compile with MinGW (32 bit, installed a few weeks ago) in an updated Windows 10 (64 bit) environment.
Standard library headers are allowed to include any other standard library header.
It's possible that <algorithm> includes <limits> and there exists std::numeric_limits::epsilon() there. And of course macros ignore namespaces and classes, so it would try to declare a function called 0.00001.
Don't use macros. Use C++ constants:
constexpr double epsilon = 0.00001;
And if you absolutely need macro, always define them after all includes. Defining them before makes your code very brittle - any change in those headers in the future might blow up your code with cryptic compiler errors.
Don't define macros in header files, for the same reason.
Prefer very localized macros when possible - define them where needed and #undef after you are done. This way they won't leak to the outside (although you can still inadvertently override an existing macro).

C++ did wrong mathematics?

I compiled this basic calculation in C++ but got wrong answers when did it on calculator. How is this possible even though i declared "ans" as "long long int"?
#include <iostream>
#include <cstdlib>
#include<vector>
#include<string>
#include <unordered_map>
#include <utility>
using namespace std;
int main(){
long long int ans=1-1000000000+1-1000000000+1-1000000000;
cout<<ans; //-2999999997
return 0;
}
the expected answer is commented against cout<<ans;
but what compiler returned is: 1294967299
please let me know where I went wrong in this.
A more modern C++ compiler will tell you what the problem is, like mine did:
warning: integer overflow in expression of type ‘int’ results in
‘1294967299’
These numbers are too big for the default size of ints on your C++ implementation. You must tell your C++ compiler that your numbers are long longs:
long long int ans=1-1000000000LL+1-1000000000LL+1-1000000000LL;
All that long long int does is tell your C++ compiler that the result of the mathematical expression is a long long int. Your problem is that you must tell your C++ compiler that the numbers it uses to compute the expression are also long longs.
It is taking ints and calculating them as ints and then storing the result in a long long. So an overflow happens before you store in long long
In order to do it right put LL at the end of each number.
Like this: 1LL instead of 1.
You went wrong not enabling compiler warnings. Assuming you're using g++ or clang++, use -Wall and you will be enlightened.

Lambda function generating "ambiguous function call" error despite lack of ambiguity

So I'm trying to deal with a program that can accept a function that either returns a vector of doubles, or just returns a single double.
Unfortunately, when I try to compile this (MSVC2010) I get the following error:
ambiguous call to overloaded function
Is there anything I'm doing that's obviously wrong? I need a way to differentiate between the two, and I'm trying to avoid hackish template metaprogramming.
#include <iostream>
#include <functional>
#include <vector>
std::vector<double> foo(std::function<std::vector<double>(unsigned int) > a){return a(10);}
double foo(std::function<double(unsigned int) > a){return a(11);}
int main(){
foo([](unsigned int)->double{return 12.0;});
return 0;
}
As you can see, my return type is explicitly declared to be a double, yet it can't decide which version of foo to call.
Should I just run back to function pointers?
Thank you very much for your time!

std::tolower and Visual Studio 2013

I try to understand how to use std::tolower...
#include <iostream>
#include <string>
#include <algorithm>
#include <locale>
int main()
{
std::string test = "Hello World";
std::locale loc;
for (auto &c : test)
{
c = std::tolower(c, loc);
}
std::transform(test.begin(), test.end(), test.begin(), ::tolower); // 1) OK
std::transform(test.begin(), test.end(), test.begin(), std::tolower); // 2) Cryptic compile error
std::transform(test.begin(), test.end(), test.begin(), static_cast<int(*)(int)>(std::tolower)); // 3) Cryptic compile error. Seems OK with other compilers though
return 0;
}
So:
Why ::tolower version is working?
Why std::tolower is not working in std::transform?
What static_cast<int(*)(int)>(std::tolower)) really is trying to do? Why
does it work with GCC and not with Visual Studio 2013?
How could I use std::lower in std::transform with Visual Studio 2013 then?
First off, note, that none of these approaches does the right thing in a portable way! The problem is that char may be signed (and typically is) but the versions of tolower() only accept positive values! That is you really want to use std::tolower() using something like this:
std::transform(test.begin(), test.end(), test.begin(),
[](unsigned char c) { return std::tolower(c); });
(or, of course, using a corresponding function object if you are stuck with C++03). Using std::tolower() (or ::tolower() for that matter) with a negative value results in undefined behavior. Of course, this only matters on platform where char is signed which seems, however, to be the typical choice.
To answer your questions:
When including <cctype> you typically get the various functions and types from the standard C library both in namespace std as well as in the global namespace. Thus, using ::tolower normally works but isn't guaranteed to work.
When including <locale>, there are two versions of std::tolower available, one as int(*)(int) and one as char(*)(char, std::locale const&). When using just std::tolower the compiler has generally no way to decide which one to use.
Since std::tolower is ambiguous, using static_cast<int(*)(int)>(std::tolower) disambiguates which version to use. Why use of static_cast<...>() with VC++ fails, I don't know.
You shouldn't use std::tolower() with a sequences of chars anyway as it will result in undefined behavior. Use a function object using std::tolower internally on an unsigned char.
It is worth noting that using a function object rather than a function pointer is typically a lot faster because it is trivial to inline the function object but not as trivial to inline the function pointer. Compilers are getting better with inlining the use of function pointers where the function is actually known but contemporary compilers certainly don't always inline function calls through function pointers even if all the context would be there.
std::tolower is overloaded in C++, it's declared in <cctype> as
int tolower(int);
and also in <locale> as
template<CharT> CharT tolower(CharT, const locale&);
so when you say "std::tolower" you get an ambiguous reference to an overloaded function.
Why ::tolower version is working?
When you include <cctype> the one-argument overload is declared in namespace std and might also be declared in the global namespace, depending on the compiler. If you include <ctype.h> then it's guaranteed to be included in the global namespace, and ::tolower will work (although note Dietmar's points about when it's not safe). The two-argument overload from <locale> is never declared in the global namespace, so ::tolower never refers to the two-argument overload.
2. Why std::tolower is not working in std::transform?
See above, it's an overloaded name.
3. What static_cast<int(*)(int)>(std::tolower)) really is trying to do?
It tells the compiler you want the int std::tolower(int) overload, not any other overload of std::tolower.
Why does it work with GCC and not with Visual Studio 2013?
Probably because you didn't include <cctype>, or (less likely) it could be a Visual Studio bug.
4. How could I use std::lower in std::transform with Visual Studio 2013 then?
If you know you only have characters with values between 0 and 127 then you can include <ctype.h> and use ::tolower (because the two-argument version is not declared in the global namespace, only in namespace std) or disambiguate which overload you want with the static cast. An alternative to the cast is to use a local variable:
typedef int (*tolower_type)(int);
tolower_type tl = &std::tolower;
std::transform(b, e, b, tl);
A safer and portable alternative is to use a custom function object (or lambda expression) to call the desired overload safely:
std::transform(b, e, b, [](unsigned char i) { return std::tolower(i); });
This uses std::tolower with an argument, so the compiler can do overload resolution to tell which overload you want to call. The parameter is unsigned char to ensure we never pass a char with a negative value to tolower(int), because that has undefined behaviour.
See http://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.simple for more details.

cout weird output

When I try using cout, it outputs a random number rather then the sentence I want. There is not compiler error, the program runs fine.
Here is my code:
//question.h
#ifndef _QUESTION_H_
#define _QUESTION_H_
using namespace std;
int first()
{
cout<<"question \n";
return 0;
}
#endif
//main.cpp
#include <iostream>
#include "question.h"
using namespace std;
void main(){
cout<<""<<first<<""<<endl;
cin.ignore();
cin.get();
}
I'm fairly new to writing my own header files, so I'm not sure if I did something wrong with that or if there's a problem with visual studio.
You're printing the address of the function. You need to call it:
cout<<""<<first()<<""<<endl;
^^
As mentioned in the comments, this doesn't have to output what you expect, either. The order in which arguments to functions (and that is just a bunch of function calls) is unspecified, so your function output could be in any position the compiler chooses. To fix this, put separate statements:
cout<<"";
cout<<first(); //evaluated, so output inside first() printed before return value
cout<<""<<endl;
It might not matter with the empty strings, but it will when you replace those with something visible.
Also, don't use void main. Use int main() or int main(int, char**) (see here). Don't use using namespace std;, especially in headers, as std has a lot of crap in it that is pulled in with that statement, leading to easy and confusing conflicts (see here). Finally, choose a name that does not conflict with identifiers reserved for the implementation as your include guard.
You are printing the address of the function first rather than calling it. But changing the function call won't fix your problem all by itself, because first writes to cout internally and then returns a number, which will be printed, which doesn't appear to be what you want.
If you want first to act like an <iomanip> thingie you have to jump through a few more hoops -- read that header to see how it's done.
Use cout<<""<<first()<<""<<endl; you need to actually call the function, not print its address