[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c++

namespace problem

Sebastian Pfützner

9/26/2008 8:44:00 AM

Hi,

the following code produces errors with VC++ and Comeau, but compiles
with g++:

#include <iostream>

namespace n
{
struct c
{
void test();

private:
struct s
{
int i;
};

friend void f(s t);
};
}

void n::c::test()
{
s t = {42};
f(t);
}

void n::f(c::s t)
{
std::cout << t.i << std::endl;
}

int main()
{
n::c().test();
}

comeau prints:
error: namespace "n" has no member "f"

vc++ prints:
error C2248: 'n::c::s' cannot access private struct declared in class 'n::c'

both point to the line 'void n::f(c::s t)'.

If I write:

namespace n
{
void f(c::s t)
{
std::cout << t.i << std::endl;
}
}

instead, everything works fine.
What is wrong with the first version?

Thanks in advance
--
Sebastian Pfützner
s.pfuetzner@onlinehome.de
ICQ-ID: 39965036
15 Answers

Barry

9/26/2008 10:06:00 AM

0

On Sep 26, 4:43 pm, Sebastian Pfützner <s.pfuetz...@onlinehome.de>
wrote:
> Hi,
>
> the following code produces errors with VC++ and Comeau, but compiles
> with g++:
>
> #include <iostream>
>
> namespace n
> {
>      struct c
>      {
>          void test();
>
>      private:
>          struct s
>          {
>              int i;
>          };
>
>          friend void f(s t);
>      };
>
> }
>
> void n::c::test()
> {
>      s t = {42};
>      f(t);
>
> }
>
> void n::f(c::s t)
> {
>      std::cout << t.i << std::endl;
>
> }

void n::f(n::c::s t)
{
...
}

If I don't miss something, then the code above should work,
But anyway, my gcc (4.3), cl (8.0) both fails to compile again.


>
> int main()
> {
>      n::c().test();
>
> }
>
> comeau prints:
> error: namespace "n" has no member "f"
>
> vc++ prints:
> error C2248: 'n::c::s' cannot access private struct declared in class 'n::c'
>
> both point to the line 'void n::f(c::s t)'.
>
> If I write:
>
> namespace n
> {
>      void f(c::s t)
>      {
>          std::cout << t.i << std::endl;
>      }
>
> }
>
> instead, everything works fine.
> What is wrong with the first version?
>
> Thanks in advance

I think there's both versions should work, as long as
the modification I mentioned above.

I guess this is due to bugs with gcc and vc.

--
Best Regards
Barry

Sebastian Pfützner

9/26/2008 10:53:00 AM

0

Barry schrieb:
> I think there's both versions should work, as long as
> the modification I mentioned above.
>
> I guess this is due to bugs with gcc and vc.

gcc works for me, but Comeau online fails. So there is a bug in Comeau too?

--
Sebastian Pfützner
s.pfuetzner@onlinehome.de
ICQ-ID: 39965036

Michael DOUBEZ

9/26/2008 11:08:00 AM

0

Sebastian Pfützner a écrit :
> Hi,
>
> the following code produces errors with VC++ and Comeau, but compiles
> with g++:
>
> #include <iostream>
>
> namespace n
> {
> struct c
> {
> void test();
>
> private:
> struct s
> {
> int i;
> };
>
> friend void f(s t);
> };
> }
>
> void n::c::test()
> {
> s t = {42};
> f(t);
> }
>
> void n::f(c::s t)
> {
> std::cout << t.i << std::endl;
> }
>
> int main()
> {
> n::c().test();
> }
>
> comeau prints:
> error: namespace "n" has no member "f"

This is true, the function f has not been declared in n.
You only declared a n::f(s) to be friend; this doesn't declare the function.


>
> vc++ prints:
> error C2248: 'n::c::s' cannot access private struct declared in class
> 'n::c'

The comopiler doesn't recognize the function name as being the friend of
n::c::s. This error is declared before the other I guess.

>
> both point to the line 'void n::f(c::s t)'.
>
> If I write:
>
> namespace n
> {
> void f(c::s t)
> {
> std::cout << t.i << std::endl;
> }
> }
>
> instead, everything works fine.
> What is wrong with the first version?

f(s) is never declared into n. You can also write:

namespace n
{
void f(c::s t);
}


void n::f(c::s t)
{
.....
}

???

9/26/2008 12:08:00 PM

0

Sebastian Pfützner ??:
> Hi,
>
> the following code produces errors with VC++ and Comeau, but compiles
> with g++:
>
> #include <iostream>
>
> namespace n
> {
> struct c
> {
> void test();
>
> private:
> struct s
> {
> int i;
> };
>
> friend void f(s t);
> };
> }
>
> void n::c::test()
> {
> s t = {42};
> f(t);
> }
>
> void n::f(c::s t)
> {
> std::cout << t.i << std::endl;
> }
>
> int main()
> {
> n::c().test();
> }
>
> comeau prints:
> error: namespace "n" has no member "f"
>
> vc++ prints:
> error C2248: 'n::c::s' cannot access private struct declared in class
> 'n::c'
>
> both point to the line 'void n::f(c::s t)'.
>
> If I write:
>
> namespace n
> {
> void f(c::s t)
> {
> std::cout << t.i << std::endl;
> }
> }
>
> instead, everything works fine.
> What is wrong with the first version?
>
> Thanks in advance

f should be declared before its implementation as it in the namespace.
i don't have VC on my PC, so the following is just what i thought to be right,so i am not sure it works with VC
you just try this.

Good luck.

namespace n
{
struct c
{

private:
struct s
{
...
};
friend void f(c::s t);
...
}

void f(c::s t);
}

void n:f(c::s t)
{
std::cout << t.i << std::endl;
}

int main()
{
...
}

Sebastian Pfützner

9/26/2008 12:56:00 PM

0

Michael DOUBEZ schrieb:
> f(s) is never declared into n. You can also write:
>
> namespace n
> {
> void f(c::s t);
> }
>
>
> void n::f(c::s t)
> {
> .....
> }

No, it doesn't compile in comeau if I add the declaration.
--
Sebastian Pfützner
s.pfuetzner@onlinehome.de
ICQ-ID: 39965036

Sebastian Pfützner

9/26/2008 12:58:00 PM

0

书å??å½­ schrieb:
> f should be declared before its implementation as it in the namespace.
> i don't have VC on my PC, so the following is just what i thought to be
> right,so i am not sure it works with VC
> you just try this.
>
> Good luck.
>
> namespace n
> {
> struct c
> {
>
> private:
> struct s
> {
> ...
> };
> friend void f(c::s t);
> ...
> }
>
> void f(c::s t);
> }
>
> void n:f(c::s t)
> {
> std::cout << t.i << std::endl;
> }
>
> int main()
> {
> ...
> }

This doesn't fix the problem, here the complete code with declaration of f:

#include <iostream>

namespace n
{
struct c
{
void test();

private:
struct s
{
int i;
};

friend void f(s t);
};

void f(c::s t);
}

void n::c::test()
{
s t = {42};
f(t);
}

void n::f(c::s t)
{
std::cout << t.i << std::endl;
}

int main()
{
n::c().test();
}

--
Sebastian Pfützner
s.pfuetzner@onlinehome.de
ICQ-ID: 39965036

Victor Bazarov

9/26/2008 1:31:00 PM

0

Sebastian Pfützner wrote:
> [..] here the complete code with declaration of f:
>
> #include <iostream>
>
> namespace n
> {
> struct c
> {
> void test();
>
> private:
> struct s
> {
> int i;
> };
>
> friend void f(s t);
> };
>
> void f(c::s t);
> }
>
> void n::c::test()
> {
> s t = {42};
> f(t);
> }
>
> void n::f(c::s t)
> {
> std::cout << t.i << std::endl;
> }
>
> int main()
> {
> n::c().test();
> }
>

I think you should ask Comeau folks for the explanation. They have a
link on their site to send a question to the compiler team, use it.

As I could understand from 3.3.1/6 (it's a note, hence non-normative,
but it explains the other elements), the name 'f' should be considered a
member of 'n', although it doesn't *introduce* that name (and that's why
you need the extra declaration to be able to use 'f' later). So the
compiler *should* connect the 'f' from the 'friend' declaration with the
'f' from the namespace declaration and *merge* them because, according
to the Standard (at least how I understand it) they declare the *same*
function.

Do ask Comeau, and then post again with any resolution. Thanks for this
interesting question!

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask

Ali Karaali

9/26/2008 2:13:00 PM

0

> I think you should ask Comeau folks for the explanation.  They have a
> link on their site to send a question to the compiler team, use it.
>
> As I could understand from 3.3.1/6 (it's a note, hence non-normative,
> but it explains the other elements), the name 'f' should be considered a
> member of 'n', although it doesn't *introduce* that name (and that's why
> you need the extra declaration to be able to use 'f' later).  So the
> compiler *should* connect the 'f' from the 'friend' declaration with the
> 'f' from the namespace declaration and *merge* them because, according
> to the Standard (at least how I understand it) they declare the *same*
> function.

void fonk (); // <-- Why do I have to declare it in here?

/* If I don't declare it,
#error `void fonk()' should have been declared inside `::'
*/

namespace MySpace
{
int a = 1, b = 2, c = 3;

class Sample
{
int m_s;

public :
Sample()
:
m_s( 0 )
{};

int getSample()
{
return this->m_s;
}

friend void ::fonk();
};

int foo (Sample sample)
{
return sample.getSample();
}

int func (int arg)
{
return arg * arg;
}
}

void fonk ()
{
MySpace::Sample sample;

cout << sample.m_s << " " << 5 << endl;
cout << "I am a friend";
}

Victor Bazarov

9/26/2008 4:00:00 PM

0

Ali Karaali wrote:
>> I think you should ask Comeau folks for the explanation. They have a
>> link on their site to send a question to the compiler team, use it.
>>
>> As I could understand from 3.3.1/6 (it's a note, hence non-normative,
>> but it explains the other elements), the name 'f' should be considered a
>> member of 'n', although it doesn't *introduce* that name (and that's why
>> you need the extra declaration to be able to use 'f' later). So the
>> compiler *should* connect the 'f' from the 'friend' declaration with the
>> 'f' from the namespace declaration and *merge* them because, according
>> to the Standard (at least how I understand it) they declare the *same*
>> function.
>
> void fonk (); // <-- Why do I have to declare it in here?
>
> /* If I don't declare it,
> #error `void fonk()' should have been declared inside `::'

Which line does it refer to? To the 'friend' declaration?

> */
>
> namespace MySpace
> {
> int a = 1, b = 2, c = 3;
>
> class Sample
> {
> int m_s;
>
> public :
> Sample()
> :
> m_s( 0 )
> {};
>
> int getSample()
> {
> return this->m_s;
> }
>
> friend void ::fonk();

I believe the reason the compiler needs 'fonk' declared in the global
namespace before you declare it here is due to your use of scope
resolution. If you didn't use it, the name would be looked up in the
namespace surrounding your class, and if the function isn't found, it
would be considered "forward declared" for the purposes of that class
definition only. But since you specified where to look for the function
by using '::', the compiler has to look and it doesn't find it.

> };
>
> int foo (Sample sample)
> {
> return sample.getSample();
> }
>
> int func (int arg)
> {
> return arg * arg;
> }
> }
>
> void fonk ()
> {
> MySpace::Sample sample;
>
> cout << sample.m_s << " " << 5 << endl;
> cout << "I am a friend";
> }

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask

Ali Karaali

9/26/2008 7:13:00 PM

0

class Sample
{
int m_s;

public :
Sample()
:
m_s( 0 )
{};

int getSample()
{
return this->m_s;
}

friend void fonk();
};

int foo (Sample sample)
{
return sample.getSample();
}

When the namespace dropped, everything is fine. And you don't have to
use forward declaration. As I know, the friend decleration in a class
means a function prototype. As you see the above. But when we put the
namespace, it don't work.

I really don't understand why does the compiler need the forward
decleration when we put the namespace?

namespace MySpace
{
class Sample
{
int m_s;

public :
Sample()
:
m_s( 0 )
{};

int getSample()
{
return this->m_s;
}

friend void ::fonk();
};
}

void fonk ()
{
MySpace::Sample sample;

cout << sample.m_s << " " << 5 << endl;
cout << "I am a friend";
}