I am new to templates in c++.
i was trying some small programs.
CPP [80]> cat 000001.cpp 000001.hpp
#include <iostream>
#include <string>
#include "000001.hpp"
int main()
{
int i = 42;
std::cout << "max(7,i): " << ::max(7,i) << std::endl;
double f1 = 3.4;
double f2 = -6.7;
std::cout << "max(f1,f2): " << ::max(f1,f2) << std::endl;
std::string s1 = "mathematics";
std::string s2 = "math";
std::cout << "max(s1,s2): " << ::max(s1,s2) << std::endl;
}
template <typename T>
inline T const& max (T const& a, T const& b)
{
return a < b ? b : a;
}
when i compile this program:
i get an error below:
CPP [78]> /opt/aCC/bin/aCC -AA 000001.cpp
Error (future) 229: "/opt/aCC/include_std/string.cc", line 164 # "Ambiguous overloaded function call; a
function match was not found that was strictly best for ALL arguments. Two functions that matched
best for some arguments (but not all) were "const unsigned long &max<unsigned long>(const unsigned
long &,const unsigned long &)" ["000001.hpp", line 2] and "const unsigned long &std::max<unsigned
long>(const unsigned long &,const unsigned long &)" ["/opt/aCC/include_std/algorithm", line 1762]."
Choosing "const unsigned long &max<unsigned long>(const unsigned long &,const unsigned long &)"
["000001.hpp", line 2] for resolving ambiguity.
_C_data = _C_getRep (max (_RW::__rw_new_capacity (0, this),
^^^
Warning: 1 future errors were detected and ignored. Add a '+p' option to detect and fix them before they become fatal errors in a future release. Behavior of this ill-formed program is not guaranteed to match that of a well-formed program
Could nybody please tell me what exactly the error is?
You are probably including <iostream.h> instead of <iostream> somewhere. The former hasn't existed for some time now, but for compatibility reasons, you compiler still accepts the include and replaces it with
#include <iostream>
using namespace std;
This causes std::max to be brought to the global namespace, thus resulting in an ambiguity. Replace <iostream.h> with <iostream> or rename your max function and the problem should disappear.
Edit: You've apparently fixed the include, but I bet you still have using namespace std; somewhere. You need to get rid of that. In fact you should never use using namespace in the global scope.
Edit: You might also have using std::max somewhere. You need to get rid of it too.
The code you've posted compiles just fine, there must be something else that is wrong inside "000001.hpp". Can you post the contents of that file too?
Edit: If you do as avakar says but the problem persists, that must be due to some problem with your compiler. There are two obvious workarounds I can think of: rename your max function to something else, or put it in a namespace:
namespace Foo
{
template <typename T>
inline T const& max (T const& a, T const& b)
{
return a < b ? b : a;
}
}
int main()
{
int i = 42;
std::cout << "max(7,i): " << Foo::max(7,i) << std::endl;
double f1 = 3.4;
double f2 = -6.7;
std::cout << "max(f1,f2): " << Foo::max(f1,f2) << std::endl;
std::string s1 = "mathematics";
std::string s2 = "math";
std::cout << "max(s1,s2): " << Foo::max(s1,s2) << std::endl;
}
I don't know which compiler you are using but the second error tells you that the two following functions are clashing :
::max
std::max
It seems really weird, you may have a using namespace std; somewhere or worse, that one of your include use iostream.h as noted in the first error. Could you give more information about your compiler/toolchain and the content of your .hpp file?
It says that two definitions for
max<unsigned long>
were found. One definition is in 000001.hpp and the other is in /opt/aCC/include_std/algorithm. The compiler chose the one in 000001.hpp for now, so no error is present now. But it says that these two definitions may cause errors in the future.
I don't know if this causes the problem, but anyhow; you shouldnt use the name max for your global (or local) function as it is a part of STL.
Related
#include <iostream>
void hi(int x) {
std::cout << "hi\n";
}
void hi(int64_t y) {
std::cout << "hi2\n";
}
int main() {
hi(3LL);
}
Why does it throw ambiguous match? I think it should resolves to the second function since it's an exact match. Or is int64_t a different type from 3LL?
It seems that the error only occurs on some compiler, namely g++ but not clang. Not sure if it is caused by different compiler flags or version used though.
Or is int64_t a different type from 3LL?
Yes, int64_t is long (in this implementation). 3LL is long long.
Modern IDE have a "go to definition" feature, where you can position your cursor over int64_t and go to https://github.com/lattera/glibc/blob/master/bits/stdint-intn.h#L27 and then go to https://github.com/lattera/glibc/blob/master/posix/bits/types.h#L43 .
I ask this for understanding, In c there is no name mangling but c++ has. How this works for example say I have following files
exlib.hpp header file
exlib.cpp function implemented file
exapp.cpp main function using exlib
File exlib.hpp
#ifndef EXLIB
#define EXLIB
#include <iostream>
int sum(int, int);
int sum(int, int, int);
int sum(int, int, int, int);
#endif
File exlib.cpp
#include "exlib.hpp"
int sum(int a, int b)
{
std::cout << "In sum(int, int)" << std::endl;
return a + b;
}
int sum(int a, int b, int c)
{
std::cout << "In sum(int, int, int)" << std::endl;
return a + b + c;
}
int sum(int a, int b, int c, int d)
{
std::cout << "In sum(int, int, int, int)" << std::endl;
return a + b + c + d;
}
File exapp.cpp
#include "iostream"
#include "exlib.hpp"
int main()
{
std::cout << "Sum = " << sum(1, 1) << std::endl;
std::cout << "Sum = " << sum(2, 2, 2) << std::endl;
std::cout << "Sum = " << sum(3, 3, 3, 3) << std::endl;
}
Compile
$ g++ -c exlib.cpp
$ g++ exapp.cpp exlib.o -o exapp
$ ./exapp
sum in exlib.o are name mangled right ?
output:
Sum = In sum(int, int)
2
Sum = In sum(int, int, int)
6
Sum = In sum(int, int, int, int)
12
How sum correctly called after name mangle in main ?, There is any rules for name mangling that same name is replaced in main or How they identify?
All programming language mangle name in same way ?
Thanks.
While C++ offers Polymorphism (i.e. different things can be named equal in the same scope by using other features for distinguishing them), this is not supported by linkers (neither in statical nor dynamical linking). So, C++ compilers uses name mangling. (The other features are used to decorate the original identifier to produce a unique name.)
A C++ compiler compiles each C++ file (aka. translation unit) on its own. Hence, it is obvious that the name mangling has to be done in a unique, reproducible way by this compiler. I.e. the same declaration has to be mapped to the same symbol always.
Otherwise, it would be impossible for the linker to resolve symbols that were declared (only) in one file and defined in another.
However, there isn't a general name-mangling standard (e.g. as part of the C++ standard).
So, even on the same platform, the binary codes produced by two different compilers may be incompatible due to different name-mangling (as well as other details).
(For MS Visual C++, this makes even binaries from distinct versions incompatible.)
To overcome this, there exist Application Binary Interfaces (ABIs) for certain platforms (e.g. Linux).
One detail of an ABI is a standardized name-mangling.
This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 2 years ago.
I'm having some difficulty reproducing an example program of Object-Oriented Programming Using C++ described in "Encapsulation and Type Extensibility."
For simplicity's sake, I've cut out most of the code to focus on the specific error at hand:
#include <iostream> // Access standard IO library
#include <string> //Access type 'string'
using namespace std; //Use standard library namespace
const int max_length = 255;
class my_string {
public:
void assign(const char* st);
int length() const { return len; }
void print() const
{ cout << s << "\nLength: " << len << endl; }
private:
char s[max_length];
int len;
};
int main()
{
my_string one;
one.assign("I'm sorry Dave, I'm afraid I can't do that.");
one.print();
system("PAUSE");
}
When I try to compile, I get the error message:
[Linker error] undefined reference to 'my_string::assign(char const*)'
I'm not sure what I'm doing wrong. My best guess is that assign is incorrectly defined, since the main() block seems fine.
Edit:
The complete example as written in the book is:
In file string1.cpp
const int max_len = 255;
class my_string {
public:
void assign(const char* st);
int length() const { return len; }
void print() const
{ cout << s << "\nLength: " << len << endl; }
private:
char s[max_length];
int len;
};
int main()
{
my_string one, two;
char three[40] = {"My name is Charles Babbage."};
one.assign("My name is Alan Turing.");
two.assign(three);
cout << three;
cout << "\nLength: " << strlen(three) << endl;
if (one.length() <= two.length())
one.print();
else
two.print();
}
Linking and compiling errors are two different things. A compiler error means that you did something wrong in the syntax.
A linking error tells you that there is a part missing when the linker tries to put your program together.
[Linker error] undefined reference to 'my_string::assign(char const*)'
This error tells you that somewhere the promise was made to the compiler that my_string::assign(char const*) exists and can be used (by a declaration void assign(const char* st);). But in the linking step the linker cannot find that function.
If the error references a function that you have written, then you might have forgotten the definition of it or have mismatching signature between declaration and definition.
The compiler can't find it's definition.
Usually there is a header file (.h) where the class' declaration is put, including as less as possible and a source file (.cpp) that includes all the definitions.
The header file declarations tells the compiler which methods shall be available (as a promise),
the source file should contain the definition of the functions that are declared in the header file.
If they aren't defined, meaning there is no body for that function, it can't be executed. In your book, the code is both declared and defined, by writing the methods inside the class' definition.
You could do the same:
public:
void assign(const char* st) {
/* implementations of the assign method here
(or leave it empty for this example, but rather don't)*/
};
int length() const { return len; };
...
I am learning overloading an inline function.
In testing this code I can't compile with the following errors I can't understand as to what's wrong.
I tested it with only 1 inline function and works but a second breaks it. Can you please share some guidance:
Thank you for your help, Sergio
Compiler errors:
abs exception specification does not match previous declaration line 13
function long abs (const long) throw() already has body line 13
abs redefinition; different exception specification line 19
abs error in function definition or declaration; function not called line 30
abs error in function definition or declaration; function not called line 32
#include "pch.h"
#include <iostream>
using namespace std;
// Overload abs() three ways
inline int abs(int n)
{
cout << "In integer abs() \n";
return((n < 0) ? -n : n);
}
inline long abs(long n)
{
cout << "In long abs() \n";
return((n < 0) ? -n : n);
}
inline double abs(double n) {
cout << "In double abs() \n";
return ((n < 0 ? -n : n));
}
int main()
{
cout << "Absolute value of -10 Is ";
cout << abs(-10) << "\n";
cout << "Absolute value of -10L Is ";
cout << abs(-10L) << "\n";
cout << "Absolute value of -10.01 Is ";
cout << abs(-10.01) << "\n";
}
Your error is here:
using namespace std;
since this brings into the global namespace the definitions of the function overloads std::abs() (they are declared & defined in cmath which appears to be #included directly or indirectly into iostream), which then clash with your own definitions. The above statement (using namespace std;) is almost never a good idea, certainly not in a header file -- it is, unfortunately, commonly used in online coding contests to simplify code (no need for std::).
Btw, this has only do with inline inasmuch as the function definitions (not the declarations) clash, which must be declared inline in header files to obtain the proper linkage.
Precense of using namespace std; causes a conflict with ::std::abs function. However getting rid of using namespace std; will not solve the issue complitely.
The primary problem here is the use of a non-unique name for a function in global namespace. abs is a function from C standard library therefore you should not use this name for your own functions. Otherwise your may get an error if <stdlib.h> is included somewhere, or even a random Undefined Behavior because of ODR violation.
In order to prevent name conflicts in C++ you should typically define new functions in custom namespace:
n_sergio_solorzano_stuff
{
// Overload abs() three ways
inline int abs(int n)
{
...
or select globally unique names when you need to add something into global namespace:
inline int sergio_solorzano_stuff_abs(int n)
I tried to search for this specific problem and did not find anythying concrete.
I was using an undeclared variable in my program and the compiler did not complain, it just gave a warning and the program runs fine. My gcc version is 4.1.2
Below is a sample program I wrote to reproduce this, the variable "index" is not declared, why is the compiler treating "index" as a function and where does it find the definition of the function?
#include <iostream>
using namespace std;
int testfunction()
{
try {
cout << "inside testfunction method\n";
return 2;
} catch(...) {
cout << "caught exception" << index << endl;
}
return 1;
}
int main()
{
cout << "Testfunction return value : " << testfunction() << endl;
}
Compiling:
~ g++ throwreturntest.cpp
throwreturntest.cpp: In function ���int testfunction()���:
throwreturntest.cpp:11: warning: the address of ���char* index(const char*, int)���, will always evaluate as ���true���
Running :
~ ./a.out
inside testfunction method
Testfunction return value : 2
Looks like index is the name of a GCC builtin function:
http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html
So it is already declared, just not by you.
The compiler is quite verbose about the situation. It things that index is an address of a function with signature
char *index(const char *s, int c);
See man index(3). The corresponding header is somewhere in the chain of <iostream>