473,563 Members | 2,696 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

namespaces, linkage error, operator overloading

I am using Visual C++ 2007 to build the code below. I keep getting
linkage error. Could someone please tell me what I am doing wrong? The
code works until I start using namespace for my objects.

Error 1 error LNK2019: unresolved external symbol "class
std::basic_ostr eam<char,struct std::char_trait s<char & __cdecl
graph::operator <<(class std::basic_ostr eam<char,struct
std::char_trait s<char &,class graph::Node &)" (??6graph@@YAAA V?
$basic_ostream@ DU?$char_traits @D@std@@@std@@A AV12@AAVNode@0@ @Z)
referenced in function _main Program.obj

//Node.h
#ifndef NODE_H
#define NODE_H

#include <string>
#include <iostream>

using std::ostream;
using std::string;

namespace graph {
class Node
{
friend ostream &operator<<(ost ream &, Node &);
public:
Node(void);
Node(const string id);
~Node(void);

string getId() const;
void setId(const string &);
private:
string id;
};
}

#endif

//Node.cpp
#include "Node.h"

using graph::Node;

namespace graph {
Node::Node(void )
{
}
Node::Node(cons t string id) {
}

Node::~Node(voi d)
{
}

string Node::getId() const {
return id;
}

void Node::setId(con st string &id) {
this->id = id;
}
}

ostream &operator<<(ost ream &output, Node &node) {
output << node.getId();
return output;
}

//Program.cpp
#include "Node.h"

using graph::Node;
using std::cout;
using std::endl;

int main() {
Node a("a");
Node b("b");

cout << a << " and " << b << endl;
}

Apr 14 '07 #1
11 3796
#ifndef NODE_H
#define NODE_H

#include <string>
#include <iostream>

using std::ostream;
using std::string;

namespace graph {
class Node
{
public:
friend ostream &operator<<(ost ream &, Node &);
Node(void);
Node(const string id);
~Node(void);

string getId() const;
void setId(const string &);
private:
string id;
};

}

#endif

//Node.cpp

using graph::Node;

namespace graph {
Node::Node(void )
{
}

Node::Node(cons t string id) {
}

Node::~Node(voi d)
{
}

string Node::getId() const {
return id;
}

void Node::setId(con st string &id) {
this->id = id;
}

ostream &operator<<(ost ream &output, Node &node) {
output << node.getId();
return output;
}
}

//Program.cpp

using graph::Node;
using std::cout;
using std::endl;

int main() {
Node a("a");
Node b("b");

cout << a << " and " << b << endl;
}

Fixes it.

Apr 14 '07 #2
Could you help to explain what happens by declaring the operator<<
inside public as opposed to outside? I am using C++, How to Program by
Deitel/Deitel (3rd edition) as a reference. On page 528, they talk
about implementation of operator overloading as member versus non-
member functions. This is their guidance:

1. (), [], ->, or any assignment operator must be implemented as
member function
2. when an operator function is implemented as a member function, the
leftmost operand must be a class object of the operator's class ... if
the left operand must be an object of a different class or built-in
type, this operator function must be implemented as a non-member
function.

They specifically state that << and >operators should be implemented
as non-member functions. Doesn't this mean outside public (as I had in
the original post)?

Thanks.

On Apr 14, 5:14 pm, "twomers" <twom...@gmail. comwrote:
#ifndef NODE_H
#define NODE_H

#include <string>
#include <iostream>

using std::ostream;
using std::string;

namespace graph {
class Node
{
public:
friend ostream &operator<<(ost ream &, Node &);
Node(void);
Node(const string id);
~Node(void);

string getId() const;
void setId(const string &);
private:
string id;
};

}

#endif

//Node.cpp

using graph::Node;

namespace graph {
Node::Node(void )
{
}

Node::Node(cons t string id) {
}

Node::~Node(voi d)
{
}

string Node::getId() const {
return id;
}

void Node::setId(con st string &id) {
this->id = id;
}

ostream &operator<<(ost ream &output, Node &node) {
output << node.getId();
return output;
}

}

//Program.cpp

using graph::Node;
using std::cout;
using std::endl;

int main() {
Node a("a");
Node b("b");

cout << a << " and " << b << endl;

}

Fixes it.

Apr 14 '07 #3

jakester wrote:
I am using Visual C++ 2007 to build the code below. I keep getting
linkage error. Could someone please tell me what I am doing wrong? The
code works until I start using namespace for my objects.
In this case, I'm not sure the compiler is totally compliant, however, I
don't think the error is the issue.
>
Error 1 error LNK2019: unresolved external symbol "class
std::basic_ostr eam<char,struct std::char_trait s<char & __cdecl
graph::operator <<(class std::basic_ostr eam<char,struct
^^^^^^^^^^^^^^^ ^^^

Notice the graph:
std::char_trait s<char &,class graph::Node &)" (??6graph@@YAAA V?
$basic_ostream@ DU?$char_traits @D@std@@@std@@A AV12@AAVNode@0@ @Z)
referenced in function _main Program.obj

//Node.h
#ifndef NODE_H
#define NODE_H

#include <string>
#include <iostream>

using std::ostream;
using std::string;
notice, this is outside the graph: - In this case I suggest you don't do
this using in a header.
>
namespace graph {
class Node
{
friend ostream &operator<<(ost ream &, Node &);
OK - friend in this case injects a declaration into the enclosing
namespace, i.e. graph. But, this probably doesn't do what you think you
want it to do since operator<< is a template not a straight function.

BTW - you really want a const Node &
public:
Node(void);
Node(const string id);
~Node(void);

string getId() const;
// don't have to do this - but it's prolly a good idea to return a
// const std::string & here.
void setId(const string &);
private:
string id;
};
}

#endif

//Node.cpp
#include "Node.h"

using graph::Node;

namespace graph {
Node::Node(void )
{
}
Node::Node(cons t string id) {
}

Node::~Node(voi d)
{
}

string Node::getId() const {
return id;
}

void Node::setId(con st string &id) {
this->id = id;
}
}
This is being defined in the global namespace.
ostream &operator<<(ost ream &output, Node &node) {
output << node.getId();
return output;
}

//Program.cpp
#include "Node.h"

using graph::Node;
using std::cout;
using std::endl;

int main() {
Node a("a");
Node b("b");

cout << a << " and " << b << endl;
}

when I compile your code on gcc I get this :

friendop1.cpp: In function 'int main()':
friendop1.cpp:6 9: error: ambiguous overload for 'operator<<' in
'std::cout << a'
friendop1.cpp:5 3: note: candidates are: std::ostream&
operator<<(std: :ostream&, graph::Node&)
friendop1.cpp:1 1: note: std::ostream&
graph::operator <<(std::ostream &, graph::Node&)

Which is more like what I expect but I don't think that's totally right
either - not sure but it is irrelevant.

The code at the end of this posting shows somthing that does compile and
run on gcc (probably will also on VC).

Some people will object to adding things to the std namespace some
people will say that this is specifically allowed. I've seen some
compilers that won't work too well if it's not in the std:: namespace so
that's why I put it there but it may have been a buggy compiler.
--------------------------------------------------------------
#include <iostream>
#include <string>
namespace graph {
class Node;
}

namespace std {

template<
typename i_char_type,
class i_traits
>
basic_ostream<i _char_type, i_traits>& operator << (
basic_ostream<i _char_type, i_traits & i_ostream,
const graph::Node & i_value
);

} // end namespace

namespace graph {
class Node
{
// friend decl
template<
typename i_char_type,
class i_traits
>
friend
std::basic_ostr eam<i_char_type , i_traits>& std::operator << (
std::basic_ostr eam<i_char_type , i_traits & i_ostream,
const Node & i_value
);

public:
Node(void);
Node(const std::string id);
~Node(void);

const std::string & getId() const;
void setId(const std::string &);
private:
std::string id;
};
}

namespace std {

template<
typename i_char_type,
class i_traits
>
basic_ostream<i _char_type, i_traits>& operator << (
basic_ostream<i _char_type, i_traits & i_ostream,
const graph::Node & i_value
) {
i_ostream << i_value.getId() ;
return i_ostream;
}
} // end namespace
//#endif

//Node.cpp
//#include "Node.h"

using graph::Node;

namespace graph {
Node::Node(void )
{
}
Node::Node(cons t std::string id) :id(id) {
}

Node::~Node(voi d)
{
}

const std::string & Node::getId() const {
return id;
}

void Node::setId(con st std::string &id) {
this->id = id;
}
}

//Program.cpp
//#include "Node.h"

using graph::Node;
using std::cout;
using std::endl;

int main() {
Node a("a");
Node b("b");

cout << a << " and " << b << endl;
}
Apr 14 '07 #4
On Apr 14, 11:14 pm, "twomers" <twom...@gmail. comwrote:

[...]
namespace graph {
[...]
ostream &operator<<(ost ream &output, Node &node) {
If this declaration compiles, it's time to change compilers,
fast. It's not, and never has been, legal C++; a member
operator<< takes only one (explicit) parameter.
output << node.getId();
return output;
}
}
--
James Kanze (Gabi Software) email: ja*********@gma il.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Apr 15 '07 #5
On Apr 14, 11:50 pm, Gianni Mariani <gi3nos...@mari ani.wswrote:
jakester wrote:
I am using Visual C++ 2007 to build the code below. I keep getting
linkage error. Could someone please tell me what I am doing wrong? The
code works until I start using namespace for my objects.
[...]
using std::ostream;
using std::string;
notice, this is outside the graph: - In this case I suggest
you don't do this using in a header.
I agree that I don't like using declarations at global scope,
especially in a header. But I don't think that it has any
relationship with his problem.
namespace graph {
class Node
{
friend ostream &operator<<(ost ream &, Node &);
OK - friend in this case injects a declaration into the enclosing
namespace, i.e. graph. But, this probably doesn't do what you think you
want it to do since operator<< is a template not a straight function.
His operator<< is not a template. On the other hand, he *has*
effectively declared a function graph::operator <<. When
overload resolution choses this function, it will look for an
implementation in the namespace graph.

[...]
This is being defined in the global namespace.
ostream &operator<<(ost ream &output, Node &node) {
output << node.getId();
return output;
}
Which means that it is a different function. And that he still
doesn't have a definition for the friend function in namespace
graph which he declared in the header.
//Program.cpp
#include "Node.h"
using graph::Node;
using std::cout;
using std::endl;
int main() {
Node a("a");
Node b("b");
cout << a << " and " << b << endl;
}
when I compile your code on gcc I get this :
friendop1.cpp: In function 'int main()':
friendop1.cpp:6 9: error: ambiguous overload for 'operator<<' in
'std::cout << a'
friendop1.cpp:5 3: note: candidates are: std::ostream&
operator<<(std: :ostream&, graph::Node&)
friendop1.cpp:1 1: note: std::ostream&
graph::operator <<(std::ostream &, graph::Node&)
Which is more like what I expect but I don't think that's totally right
either - not sure but it is irrelevant.
Are you sure you compiled the same code? There was no
"::operator <<( std::ostream&, graph::Node& )" (the first
candidate g++ mentions above) visible in Program.cpp.

If you put all of the code in a single file, I'm not 100% sure,
but I think g++ would be right. Normal name lookup finds the
global function, and ADL finds the function in the namespace, so
both are in the overload set (along with a lot of other
functions from std, which are eliminated because they can't be
called with the given arguments). In his example, he had two
source files; graph::operator << was the only version visible in
the header.

Note that the name of the friend function graph::operator <<
isn't actually directly visible in namespace graph; friend name
injection was removed by the standards committee. But the
function will be found by ADL. If that's the only function that
the compiler sees (case in the original code), then that's what
overload resolution will choose, and since he's not implemented
it, he gets the error message he saw. If there is also another
function, with the exact same paramters, then the call is
ambiguous.
The code at the end of this posting shows somthing that does compile and
run on gcc (probably will also on VC).
Some people will object to adding things to the std namespace some
people will say that this is specifically allowed.
It depends on what you add.
I've seen some
compilers that won't work too well if it's not in the std:: namespace so
that's why I put it there but it may have been a buggy compiler.
--------------------------------------------------------------
#include <iostream>
#include <string>
namespace graph {
class Node;
}
namespace std {

template<
typename i_char_type,
class i_traits
>
basic_ostream<i _char_type, i_traits>& operator << (
basic_ostream<i _char_type, i_traits & i_ostream,
const graph::Node & i_value
);
That's illegal, I think. About the only thing your allowed to
add are specializations of existing templates, not new
templates. But why be complicated? If he defines operator<< in
the namespace graph, in his .cpp, everything should be just
fine.

--
--
James Kanze (Gabi Software) email: ja*********@gma il.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Apr 15 '07 #6
On Apr 14, 11:34 pm, "jakester" <vangj...@googl email.comwrote:
Could you help to explain what happens by declaring the operator<<
inside public as opposed to outside?
First, ignore my previous response to twomers posting; I misread
namespace for class. (It's late here.)
I am using C++, How to Program by
Deitel/Deitel (3rd edition) as a reference. On page 528, they talk
about implementation of operator overloading as member versus non-
member functions. This is their guidance:
1. (), [], ->, or any assignment operator must be implemented as
member function
2. when an operator function is implemented as a member function, the
leftmost operand must be a class object of the operator's class ... if
the left operand must be an object of a different class or built-in
type, this operator function must be implemented as a non-member
function.
They specifically state that << and >operators should be
implemented as non-member functions. Doesn't this mean
outside public (as I had in the original post)?
Non-member means that they are not members of the class. (A
friend declaration does not declare a member of the class.)
They still have to be defined in the correct namespace. Two
functions with the same names in different namespaces are
different functions.

--
James Kanze (Gabi Software) email: ja*********@gma il.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Apr 15 '07 #7
James Kanze wrote:

....
>
>I've seen some
compilers that won't work too well if it's not in the std:: namespace so
that's why I put it there but it may have been a buggy compiler.
>--------------------------------------------------------------
#include <iostream>
#include <string>
>namespace graph {
class Node;
}
>namespace std {

template<
typename i_char_type,
class i_traits
> >
basic_ostream< i_char_type, i_traits>& operator << (
basic_ostream<i _char_type, i_traits & i_ostream,
const graph::Node & i_value
);

That's illegal, I think.
In my recollection I see 50/50 with responses on that one with no one
truly convinced that it is legal or illegal. Since you can't
"specialize " a function (like you can a class), however, specialization
is accomplished by overlaoding a function. For all intents and
purposes, overloading is specialization for functions. So, was/is it
the intent of the standard to not allow overloading ? I don't believe
I've come across a definitive answer.
... About the only thing your allowed to
add are specializations of existing templates, not new
templates. But why be complicated? If he defines operator<< in
the namespace graph, in his .cpp, everything should be just
fine.
You're probably right. I remember having problems overloading
operator<< in different namespaces in the past and what I did above
solved the problem. I more than likely was a buggy compiler that didn't
handle argument dependent lookup and the work-around is no longer needed.
Apr 15 '07 #8
On Apr 15, 3:26 am, Gianni Mariani <gi3nos...@mari ani.wswrote:
James Kanze wrote:
...
I've seen some
compilers that won't work too well if it's not in the std:: namespace so
that's why I put it there but it may have been a buggy compiler.
--------------------------------------------------------------
#include <iostream>
#include <string>
namespace graph {
class Node;
}
namespace std {
template<
typename i_char_type,
class i_traits
basic_ostream<i _char_type, i_traits>& operator << (
basic_ostream<i _char_type, i_traits & i_ostream,
const graph::Node & i_value
);
That's illegal, I think.
In my recollection I see 50/50 with responses on that one with no one
truly convinced that it is legal or illegal.
The standard says it's illegal; there's no doubt about that. In
practice, however, I think the probability of it causing
problems is about 0.
Since you can't "specialize " a function (like you can a
class), however, specialization is accomplished by overlaoding
a function.
The standard is clear: a program may add template
specializations to namespace std. Nothing about overloads.
Specialization and overloading are two very different things.
For all intents and
purposes, overloading is specialization for functions.
>From where do you get that? For some very specific purposes,
specialization and overloading play similar rules. But in
general, they are two very different mechanisms, with different
rules accross the board.
So, was/is it
the intent of the standard to not allow overloading ? I don't believe
I've come across a definitive answer.
I'd say that the actual words in the standar are a definitive
answer. If you don't think that that they express the actual
intent, a defect report would be in order; to date, there isn't
one concerning this point, which means that it seems clear, and
means what it seems to mean.
... About the only thing your allowed to
add are specializations of existing templates, not new
templates. But why be complicated? If he defines operator<< in
the namespace graph, in his .cpp, everything should be just
fine.
You're probably right. I remember having problems overloading
operator<< in different namespaces in the past and what I did above
solved the problem.
And I confused namespace and class in my first reading of his
problem. One gets an idea in one's head, and one doesn't see
what is actually written. I think it's human nature; at least,
I've never met anyone who was immune to it.

--
James Kanze (Gabi Software) email: ja*********@gma il.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Apr 15 '07 #9
James Kanze wrote:
On Apr 15, 3:26 am, Gianni Mariani <gi3nos...@mari ani.wswrote:
....
>For all intents and
purposes, overloading is specialization for functions.
>>From where do you get that?
I'm saying (or intending on saying) what you're ...

.... For some very specific purposes,
specialization and overloading play similar rules.
.... saying here.

.... But in
general, they are two very different mechanisms, with different
rules accross the board.
Yes. That's the point.
>
>So, was/is it
the intent of the standard to not allow overloading ? I don't believe
I've come across a definitive answer.

I'd say that the actual words in the standar are a definitive
answer. If you don't think that that they express the actual
intent, a defect report would be in order; to date, there isn't
one concerning this point, which means that it seems clear, and
means what it seems to mean.
Ok - it probably needs to be expressed as a defect report because of the
confusion. I also don't see there ever being a problem to overload into
the std:: namespace as a way of extending support for user types.
Apr 15 '07 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

12
1982
by: Santiago de Compostela | last post by:
Hi The following program doesn't compile on MS VC++ or Bloodshed Dev-C++ #include <iostream> int strlen(const char *in) {
2
2247
by: glen stark | last post by:
Hi. I had an interesting experience with a brand x compiler recently. I had class defined within a namespace, and in that class I declared the "<<" operator as a friend to that class. Then, in the cpp code I implemented the operator overloading within a "using namespace" context, only to get access errers. To get it to work I had to put...
4
2434
by: Tron Thomas | last post by:
I have read that anonymous namespaces are preferred in C++ over declaring global statics because the namespace can hide information from other translation units and at the same time provide external linkage allowing members of the namespace to be used as template arguments. I'm not quite sure I'm clear on what this really means. What is an...
12
2957
by: RA Scheltema | last post by:
Hi all, I have the following code: namespace A { inline void func(int) { ...; } inline void func(float) { ...; } inline void func(char) { ...; } }
22
5971
by: Ian | last post by:
The title says it all. I can see the case where a function is to be called directly from C, the name mangling will stuff this up. But I can't see a reason why a template function can't be given extern "C" linkage where it is to be assigned to a C function pointer. Ian
10
6144
by: Mark A. Gibbs | last post by:
I have a question about mixing C and C++. In a C++ translation unit, I want to define a function with internal linkage and C calling convention. Here's a sample of what I want to do: // main.cpp // This is defined in a C module extern "C" void fake_qsort(void*, std::size_t, std::size_t, int (*compare)(const void*, const void*));
2
1854
by: Beeeeeeeeeeeeves | last post by:
Does C# really HAVE to have namespaces? Isn't there any way I can turn them off? I did a bit of dabbling in VB.NET but have decided not to switch to it permanantly as I've got too much pre-written generic code in C# and the cast operator overloading thing but one of the things I like about VB.NET is it doesn't enthrust the pointless idea of...
8
2582
by: andrew browning | last post by:
I am getting an istream overloading error that looks like this: error: no match for 'operator>>' in 'ins >> target->abrowning_rational::Rational::numerator' Below is the .h file: #ifndef RATIONAL #define RATIONAL #include <iostream>
1
4233
by: thetrueaplus | last post by:
Hey all. I posted this originally: http://groups.google.com/group/comp.lang.c++/browse_thread/thread/b1e4b76201ce17f1 I got the enums to work how I like but I am having a problem with the overloading of the assignment operator: namespace UserAffilliationType {
0
7583
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language...
0
7885
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
0
8106
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
0
6250
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
1
5484
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes...
0
5213
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...
0
3626
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2082
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
0
923
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.