#Classes and friends
57 messages · Page 1 of 1 (latest)
When your question is answered use !solved to mark the question as resolved.
Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.
you need to have a forward declaration of the function outside of the class then
inside the namespace?
can you not explicitly specify the scope of friend function?
friend void ::foo(); like this?
Hmm I see
the friend function takes a reference to an object of the class as a parameter tho
error: 'string' does not name a type
std::ostream& operator<<(std::ostream& out, const string& s);
then you also have to forward declare that 😄
where string is the class name
namespace A {
struct Example;
}
namespace B {
void foo(const A::Example&);
}
namespace A {
struct Example {
friend void B::foo(const Example&);
private:
int i = 123;
};
}
do the members of Example need to be forward declared as well?
no, you can't even do that
I'm not sure why this isn't working (ignore the fact that the buffer is not null terminated)
#include <iostream>
namespace user{
class string;
}
std::ostream& operator<<(std::ostream& out, const user::string& s);
namespace user{
class string{
private:
char* m_Buffer;
unsigned int m_size;
public:
string(const char* string){
int count = 0;
while(string[count] != '\0'){
count++;
}
m_size = count;
m_Buffer = new char[m_size];
for(int i = 0; i < m_size; i++){
m_Buffer[i] = string[i];
}
}
friend std::ostream& operator<<(std::ostream& out, const string& s);
};
}
std::ostream& operator<<(std::ostream& out, const string& s){
out << s.m_Buffer;
return out;
}
using namespace user;
int main(){
string s = string("Hello");
std::cout << s << std::endl;
}
oh you want to define a steam operator?
that doesn't have to be done like this
there's no need for that to be in the global namespace
you can define that right in the class if you like:
struct Example {
friend std::ostream& operator<<(std::ostream& out, const Example& e) {
return out << e.whatever;
}
};
ah yea that's possible 😅 but I just wanted to learn how it can be done outside, it works if I don't use a namespace but not sure how to get it working when the class is inside one
then you put the operator definition inside the namespace as well
it will be found there because of ADL (argument dependent lookup)
so you can't access functions outside a namespace from inside it?
huh?
;compile
<source>:35:51: error: 'string' does not name a type; did you mean 'stdin'?
35 | std::ostream& operator<<(std::ostream& out, const string& s){
| ^~~~~~
| stdin
<source>: In function 'std::ostream& operator<<(std::ostream&, const int&)':
<source>:36:14: error: request for member 'm_Buffer' in 's', which is of non-class type 'const int'
36 | out << s.m_Buffer;
| ^~~~~~~~
<source>: In function 'int main()':
<source>:44:15: error: ambiguous overload for 'operator<<' (operand types are 'std::ostream' {aka 'std::basic_ostream<char>'} and 'user::string')
44 | std::cout << s << std::endl;
| ~~~~~~~~~ ^~ ~
| | |
| | user::string
| std::ostream {aka std::basic_ostream<char>}
<source>:7:15: note: candidate: 'std::ostream& operator<<(std::ostream&, const user::string&)'
7 | std::
you have to spell it user::string outside of the namespace
-std::ostream& operator<<(std::ostream& out, const string& s){
+std::ostream& operator<<(std::ostream& out, const user::string& s){
out << s.m_Buffer;
return out;
}
#include <iostream>
namespace user{
class string;
}
std::ostream& operator<<(std::ostream& out, const user::string& s);
namespace user{
class string{
private:
char* m_Buffer;
unsigned int m_size;
public:
string(const char* string){
int count = 0;
while(string[count] != '\0'){
count++;
}
m_size = count;
m_Buffer = new char[m_size];
for(int i = 0; i < m_size; i++){
m_Buffer[i] = string[i];
}
}
friend std::ostream& operator<<(std::ostream& out, const user::string& s);
};
}
std::ostream& operator<<(std::ostream& out, const user::string& s){
out << s.m_Buffer;
return out;
}
using namespace user;
int main(){
string s = string("Hello");
std::cout << s << std::endl;
}
;compile
<source>: In function 'std::ostream& operator<<(std::ostream&, const user::string&)':
<source>:36:14: error: 'char* user::string::m_Buffer' is private within this context
36 | out << s.m_Buffer;
| ^~~~~~~~
<source>:12:15: note: declared private here
12 | char* m_Buffer;
| ^~~~~~~~
<source>: In function 'int main()':
<source>:44:15: error: ambiguous overload for 'operator<<' (operand types are 'std::ostream' {aka 'std::basic_ostream<char>'} and 'user::string')
44 | std::cout << s << std::endl;
| ~~~~~~~~~ ^~ ~
| | |
| | user::string
| std::ostream {aka std::basic_ostream<char>}
<source>:35:15: note: candidate: 'std::ostream& operator<<(std::ostream&, const user::string&)'
35 | std::ostream& operator<<(std::ostream& out, const user::string& s){
| ^~~~~~~~
<source>:31:30: note: candidate: 'std::ostream& user::operator<<(std::ostream&,
and then like @silver tusk said you have to tell it you're talking about operator<< in the global namespace
because by default, a friend declaration puts/assumes the namespace the class is in
-friend std::ostream& operator<<(std::ostream& out, const string& s);
+friend std::ostream& ::operator<<(std::ostream& out, const string& s);
Ah, this works, thank you
but the global scope resolution :: should only be put in the declaration inside the class?
putting it outside as well gives me:
error: explicit qualification in declaration of 'std::ostream& operator<<(std::ostream&, const user::string&)'
std::ostream& ::operator<<(std::ostream& out, const user::string& s);
why is that?
it seems like it should be a warning?
You dont have to put it on the declaration outside, since the scope in which it is being declared is already taken into account.
If the declaration is present in global scope then it means that the function is present in global scope, and it shall be defined there.
but if I do this inside a namespace it works?
why does the compiler give an error tho? it doesn't like much of a deal
a friend declaration is a bit special
but other declarations just... cannot be qualified, in general
you can't be in namespace A and declare something in namespace B
(well except specializations :vv )
but here we're in the global scope using :: on an operator in the global scope?
why would C++ add rules to allow this special case of a qualified declaration that has no effect 😄
yea makes sense, thank you & @silver tusk for you time and help
Thank you and let us know if you have any more questions!
This thread is now set to auto-hide after an hour of inactivity
!solved