C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Is auto_ptr_ref still needed?
Goto page 1, 2  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
KCs
Guest





PostPosted: Sat Jan 15, 2005 3:52 am    Post subject: Is auto_ptr_ref still needed? Reply with quote



I read a lot of articles about auto_ptr, and studied some
implementations of it. To put it mildly it is a bit confusing. It is
said that an auto_ptr_ref class is needed to overcome the inability of
C++ to copy a temporary auto_ptr(function return values for example)
with a non const copy constructor. The trick is that if a temporary
auto_ptr is encountered in a copying context, the auto_ptr(auto_ptr&)
constructor cannot be selected by the compiler. Instead
auto_ptr(auto_ptr_ref) is selected because there is a conversion
operator to auto_ptr_ref in the auto_ptr class.
I made some experiences in MS VC7 (.NET 2003) and it turned out that
temporary objects could be copied with non const copy constructors.
This could mean that the whole auto_ptr_ref business is not needed
anymore. I don't know how other compilers behave, but I suspect that
the same way as VC7.
The following code was compiled with VC7. It's a simplified auto ptr
class without templates just to test temporary objects and copy
constructors. The commented part contains the auto_ptr_ref trick but
the simplified auto ptr works without it (in the same way as with it,
although with it, more temporary objects will be created). I suspect
that with the ref trick the compiler selects the constructor with the
ap_ref argument when a temporary object must be copied, because ap_ref
is a better match than ap& and not because there is no const copy
constructor.
So, my question is: Is auto_ptr_ref still needed and is my reasoning
correct?

#include "stdafx.h"

// test class to be owned by ap
class A {
int _n;
public:
A() : _n(0) {
std::cout << "default ctor A(" << _n << ")" << std::endl;
}
A(int n) : _n(n) {
std::cout << "ctor A(" << _n << ")" << std::endl;
}
~A() {
std::cout << "dtor A(" << _n << ")" << std::endl;
}
int n() {
return _n;
}
};

//class ap;
//
//struct ap_ref {
// ap_ref(ap& a) : _ref(a) {
// std::cout << "ctor ap_ref from ap&" << std::endl;
// }
// ap& _ref;
//};

class ap {
A* _val;
public:
explicit ap(A* v = 0) : _val(v) {
std::cout << "ctor ap(" <<
_val << ", " << (_val? _val->n(): -1) << ")" <<
std::endl;
}
// non const copy ctor
ap(ap& v) : _val(v.release()) {
std::cout << "copy ctor ap(" <<
_val << ", " << (_val? _val->n(): -1) << ")" <<
std::endl;
}

// ap(ap_ref r) : _val(r._ref.release()) {
// std::cout << "ctor ap from ap_ref(" <<
// _val << ", " << (_val? _val->n(): -1) << ")" <<
// std::endl;
// }

~ap() {
std::cout << "dtor ap(" << _val << ", " <<
(_val? _val->n(): -1) << ")" <<
std::endl;
delete _val;
}

A* get() const {
return _val;
}

A* release() {
A* r = _val;
_val = NULL;
return r;
}

void reset(A* v = 0) {
if (v != _val)
delete _val;
_val = v;
}

// operator ap_ref() {
// ap_ref r(*this);
// return r;
// }
};

ap source() {
return ap(new A(12));
}

void sink(ap a) {
std::cout << "sinking ap: " << a.get()->n() << std::endl;
}

int _tmain(int argc, _TCHAR* argv[]) {
// the temporary objects are copied with non const copy ctor
sink(source());
ap a = source();
ap b = a;
const ap c = b;
//ap d = c; error: c is const
return 0;
}


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Bo Persson
Guest





PostPosted: Sun Jan 16, 2005 4:14 am    Post subject: Re: Is auto_ptr_ref still needed? Reply with quote




"KCs" <kujbus.csaba (AT) freemail (DOT) hu> skrev i meddelandet
news:1105720978.885196.229350 (AT) c13g2000cwb (DOT) googlegroups.com...
Quote:
I read a lot of articles about auto_ptr, and studied some
implementations of it. To put it mildly it is a bit confusing. It is
said that an auto_ptr_ref class is needed to overcome the inability of
C++ to copy a temporary auto_ptr(function return values for example)
with a non const copy constructor. The trick is that if a temporary
auto_ptr is encountered in a copying context, the auto_ptr(auto_ptr&)
constructor cannot be selected by the compiler. Instead
auto_ptr(auto_ptr_ref) is selected because there is a conversion
operator to auto_ptr_ref in the auto_ptr class.
I made some experiences in MS VC7 (.NET 2003) and it turned out that
temporary objects could be copied with non const copy constructors.

That is an MS specific extension, for backward compatibiliy with ancient
code. If you disable extensions, you get a different result.

Quote:
This could mean that the whole auto_ptr_ref business is not needed
anymore. I don't know how other compilers behave, but I suspect that
the same way as VC7.

No, not really, unless operating in MS compatibility mode (which might
be the default, for the same reason).


Bo Persson



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
James Kanze
Guest





PostPosted: Sun Jan 16, 2005 4:41 am    Post subject: Re: Is auto_ptr_ref still needed? Reply with quote



KCs wrote:

Quote:
I read a lot of articles about auto_ptr, and studied some
implementations of it. To put it mildly it is a bit
confusing.

Sort of. I tend to just think about what I can and what I
cannot do with auto_ptr, and leave it there. No need to worry
about all of the helper classes which I will never explicitly
use.

Quote:
It is said that an auto_ptr_ref class is needed to overcome
the inability of C++ to copy a temporary auto_ptr(function
return values for example) with a non const copy constructor.

I seem to recall that there is more to it than that. The
problem is that as previously proposed, it had a copy
constructor and an assignment operator. Which meant that
something like std::vector< std::auto_ptr< T> > didn't bother
the compiler at all, even though it doesn't work. I'll admit
that this fact didn't bother me much; it's trivial to write
classes for which std::vector< T > will compile, but won't work
correctly, so one more or less... But one of the national bodies
held out, and promised a no vote on the standard unless this was
fixed.

Quote:
The trick is that if a temporary auto_ptr is encountered in a
copying context, the auto_ptr(auto_ptr&) constructor cannot be
selected by the compiler.

Right.

Quote:
Instead auto_ptr(auto_ptr_ref) is selected because there is a
conversion operator to auto_ptr_ref in the auto_ptr class.

I made some experiences in MS VC7 (.NET 2003) and it turned
out that temporary objects could be copied with non const copy
constructors.

That used to be the case with a lot of compilers. C++
originally did not ban binding a temporary to a non-const
reference. The rule was found to be error prone, and was
changed sometime in the very late 80's -- the new rule is
present in the ARM, I think.

For reasons of backward compatibility, most compilers, even
today, only generate a warning, and not an error, in this case.

Quote:
This could mean that the whole auto_ptr_ref business is not
needed anymore. I don't know how other compilers behave, but
I suspect that the same way as VC7.

I don't know of any that don't give a warning. Sun CC warns.
G++ (3.4.0) gives an error (although one would hope that there
is an option to reduce the error to a warning).

I imagine that a number of older compilers don't verify this.
But only very old complilers, Sun CC verifies it since at least
4.2, over ten years ago, and CFront 3.x did as well -- 1989, if
I'm not mistaken. If a modern compiler doesn't give at least a
warning, it is a serious error in the compiler. It's not like
it were a recent change or an innovation in the standard. And
it's not like it is difficult to do right.

Quote:
The following code was compiled with VC7.

Given the dates, I would expect at least a warning from VC++ 6.0
on. In VC++ 6.0, no warning could still be considered a not too
important error. In VC++ 7.0, it sort of makes you wonder.

--
James Kanze home: www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
David Abrahams
Guest





PostPosted: Sun Jan 16, 2005 5:24 am    Post subject: Re: Is auto_ptr_ref still needed? Reply with quote

KCs wrote:
Quote:
I read a lot of articles about auto_ptr, and studied some
implementations of it. To put it mildly it is a bit confusing. It is
said that an auto_ptr_ref class is needed to overcome the inability of
C++ to copy a temporary auto_ptr(function return values for example)
with a non const copy constructor. The trick is that if a temporary
auto_ptr is encountered in a copying context, the auto_ptr(auto_ptr&)
constructor cannot be selected by the compiler. Instead
auto_ptr(auto_ptr_ref) is selected because there is a conversion
operator to auto_ptr_ref in the auto_ptr class.
I made some experiences in MS VC7 (.NET 2003) and it turned out that
temporary objects could be copied with non const copy constructors.

That's a bug in VC7. You shouldn't use that compiler as a test of
anything having to do with conformance. Upgrade to vc7.1 and your tests
will fail.

Quote:
This could mean that the whole auto_ptr_ref business is not needed
anymore. I don't know how other compilers behave, but I suspect that
the same way as VC7.

Smile That's never a good bet.

To answer your question, auto_ptr_ref may in fact not be needed anymore,
but for a different reason. For details, see:

http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#463

--
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Alf P. Steinbach
Guest





PostPosted: Sun Jan 16, 2005 11:17 am    Post subject: Re: Is auto_ptr_ref still needed? Reply with quote

* James Kanze:
Quote:

Given the dates, I would expect at least a warning from VC++ 6.0
on. In VC++ 6.0, no warning could still be considered a not too
important error. In VC++ 7.0, it sort of makes you wonder.

#include <memory> // std::auto_ptr

struct Base{ virtual ~Base() {} };
struct Derived: public Base {};

int main()
{
std::auto_ptr<Base> p( std::auto_ptr<Derived>( new Derived ) );
} // main

VC++ 7.1:

c:program filesmicrosoft visual studio .net
2003vc7includememory(455) : warning C4717:
'std::auto_ptr<Derived>::operator<Base> std::auto_ptr_ref<Base>' :
recursive on all control paths, function will cause runtime stack
overflow

And yes, that's what it will do (a workaround is to call 'release').

But that's the standard library implementation, not the compiler, so
the upshot seems to be compiler bug + library implementation bug.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
kanze@gabi-soft.fr
Guest





PostPosted: Mon Jan 17, 2005 8:13 pm    Post subject: Re: Is auto_ptr_ref still needed? Reply with quote

Alf P. Steinbach wrote:
Quote:
* James Kanze:

Given the dates, I would expect at least a warning from VC++
6.0 on. In VC++ 6.0, no warning could still be considered a
not too important error. In VC++ 7.0, it sort of makes you
wonder.

#include <memory> // std::auto_ptr

struct Base{ virtual ~Base() {} };
struct Derived: public Base {};

int main()
{
std::auto_ptr<Base> p( std::auto_ptr<Derived>( new Derived )
);
} // main

VC++ 7.1:

c:program filesmicrosoft visual studio .net
2003vc7includememory(455) : warning C4717:
'std::auto_ptr<Derived>::operator<Base> std::auto_ptr_ref<Base>' :
recursive on all control paths, function will cause runtime stack
overflow

And yes, that's what it will do (a workaround is to call
'release').

But that's the standard library implementation, not the
compiler, so the upshot seems to be compiler bug + library
implementation bug.

You've added yet another complication. I can understand that
compilers/libraries still have some problems with the template
members of auto_ptr. The question being discussed (at least as
I undersood it) was the legality of something like:

struct A {} ;
void f( A& ) ;

void
g()
{
f( A() ) ;
}

i.e. can I bind a temporary to a non-const reference. According
to the poster, this still gives no warning in VC++ 7.0. I can
see it not being an error, but the lack of a warning is
worrisome, given the age of the language change.

I'm not sure what the problem is in your example. Without
seeing the implementation, it's impossible to say whether the
recursion is due to an error in the library or an error in
template expansion in the compiler. (The <base> after operator
looks suspicious to me.)

Note that I wouldn't really expect this to work everywhere
anyway; the original wording in the standard makes it illegal.
There is a technical correction for this, but that makes it a
very new feature.

--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Alf P. Steinbach
Guest





PostPosted: Tue Jan 18, 2005 11:09 pm    Post subject: Re: Is auto_ptr_ref still needed? Reply with quote

* [email]kanze (AT) gabi-soft (DOT) fr[/email]:
Quote:
Alf P. Steinbach wrote:

#include <memory> // std::auto_ptr

struct Base{ virtual ~Base() {} };
struct Derived: public Base {};

int main()
{
std::auto_ptr<Base> p( std::auto_ptr<Derived>( new Derived )
);
} // main

...
(The <base> after operator

Huh?

Quote:
looks suspicious to me.)


Quote:
Note that I wouldn't really expect this to work everywhere
anyway; the original wording in the standard makes it illegal.

?

Quote:
There is a technical correction for this, but that makes it a
very new feature.

Is that in C++2003?

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Gabriel Dos Reis
Guest





PostPosted: Tue Jan 18, 2005 11:19 pm    Post subject: Re: Is auto_ptr_ref still needed? Reply with quote

[email]kanze (AT) gabi-soft (DOT) fr[/email] writes:

[...]

Quote:
i.e. can I bind a temporary to a non-const reference. According
to the poster, this still gives no warning in VC++ 7.0. I can
see it not being an error, but the lack of a warning is
worrisome, given the age of the language change.

I think it is considered a feature of VC++ 7.0, and later, to bind
temporaries to non-const references, no matter what the language
standard says. I have gotten a couple of bug reports to that effect
based on what VC++ was doing with users' code.

--
Gabriel Dos Reis
[email]gdr (AT) integrable-solutions (DOT) net[/email]

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
KCs
Guest





PostPosted: Wed Jan 19, 2005 9:20 pm    Post subject: Re: Is auto_ptr_ref still needed? Reply with quote

I found that feature in the Visual Studio help under the "Microsoft
Extensions to C and C++" topic. I was not aware of this important
difference between the standard and MS extensions when I experimented
with an auto_ptr interface. I discovered that what I tried was
something close to version 1 of the auto_ptr standard, and it didn't
presented the deficiencies the v1 auto_ptr had just because I used MS
extensions.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
KCs
Guest





PostPosted: Wed Jan 19, 2005 9:24 pm    Post subject: Re: Is auto_ptr_ref still needed? Reply with quote

You are right. It turned out that MS extensions were turned on. Turning
them off the compiler complains.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Gabriel Dos Reis
Guest





PostPosted: Thu Jan 20, 2005 12:25 pm    Post subject: Re: Is auto_ptr_ref still needed? Reply with quote

"KCs" <kujbus.csaba (AT) freemail (DOT) hu> writes:

Quote:
I found that feature in the Visual Studio help under the "Microsoft
Extensions to C and C++" topic. I was not aware of this important
difference between the standard and MS extensions when I experimented
with an auto_ptr interface. I discovered that what I tried was
something close to version 1 of the auto_ptr standard, and it didn't
presented the deficiencies the v1 auto_ptr had just because I used MS
extensions.

That gives me an idea. Next time, we're going to fix a long standing
bug and we don't want to "annoy" users, I will suggest we describe the
bugs as extensions that had been turned off :-)

--
Gabriel Dos Reis
[email]gdr (AT) integrable-solutions (DOT) net[/email]

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
kanze@gabi-soft.fr
Guest





PostPosted: Sat Jan 22, 2005 4:56 am    Post subject: Re: Is auto_ptr_ref still needed? Reply with quote

Gabriel Dos Reis wrote:
Quote:
"KCs" <kujbus.csaba (AT) freemail (DOT) hu> writes:

| I found that feature in the Visual Studio help under the
| "Microsoft Extensions to C and C++" topic. I was not aware
| of this important difference between the standard and MS
| extensions when I experimented with an auto_ptr interface. I
| discovered that what I tried was something close to version
| 1 of the auto_ptr standard, and it didn't presented the
| deficiencies the v1 auto_ptr had just because I used MS
| extensions.

That gives me an idea. Next time, we're going to fix a long
standing bug and we don't want to "annoy" users, I will
suggest we describe the bugs as extensions that had been
turned off Smile

Nothing is a bug if it is documented:-).

Seriously, of course, this is probably not a bug. Originally,
C++ did allow binding a temporary to a non-const reference, and
g++ is the only compiler I use today that doesn't still allow
it. Of course, the others do give a warning, along the lines of
"anachronism", or "obsolete".

While I generally encourage support for older code, I'm not sure
how necessary this is (or should be). In this case, the change
is very, very old -- it predates the ARM, in any case. Which
means that the mass of code written before it is relatively
small, and that there has been quite a bit of time to update it.
(I think that this change was introduced about the same time the
scope of nested classes was changed. And I don't know of any
compiler today which supports the old scope of nested classes,
even with backwards compatible options.)

Of course, if none of the versions of your compler to date have
even output a warning, you do have a responsibility to your
users to not suddenly break their code. In the case of
Microsoft, of course, one can wonder how this could be the case;
their first C++ compiler post-dates the ARM by several years, so
one would expect that it at least support changes that pre-date
the ARM.

--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Gabriel Dos Reis
Guest





PostPosted: Sat Jan 22, 2005 11:24 am    Post subject: Re: Is auto_ptr_ref still needed? Reply with quote

[email]kanze (AT) gabi-soft (DOT) fr[/email] writes:

Quote:
Gabriel Dos Reis wrote:
"KCs" <kujbus.csaba (AT) freemail (DOT) hu> writes:

| I found that feature in the Visual Studio help under the
| "Microsoft Extensions to C and C++" topic. I was not aware
| of this important difference between the standard and MS
| extensions when I experimented with an auto_ptr interface. I
| discovered that what I tried was something close to version
| 1 of the auto_ptr standard, and it didn't presented the
| deficiencies the v1 auto_ptr had just because I used MS
| extensions.

That gives me an idea. Next time, we're going to fix a long
standing bug and we don't want to "annoy" users, I will
suggest we describe the bugs as extensions that had been
turned off :-)

Nothing is a bug if it is documented:-).

Seriously, of course, this is probably not a bug. Originally,
C++ did allow binding a temporary to a non-const reference, and

originally, C++ did not reserve "template" as a keyword; maybe
compilers should give syntax errors each time they're fed with
template declarations. And that should, of course, probably not be a
bug. semi :-)

Quote:
g++ is the only compiler I use today that doesn't still allow
it. Of course, the others do give a warning, along the lines of
"anachronism", or "obsolete".

It affects things like overload resolution, thus changes program
semantics in obscure ways.

Quote:
While I generally encourage support for older code, I'm not sure
how necessary this is (or should be). In this case, the change
is very, very old -- it predates the ARM, in any case. Which

Yup.

Quote:
means that the mass of code written before it is relatively
small, and that there has been quite a bit of time to update it.
(I think that this change was introduced about the same time the
scope of nested classes was changed. And I don't know of any
compiler today which supports the old scope of nested classes,
even with backwards compatible options.)

Aha.

--
Gabriel Dos Reis
[email]gdr (AT) integrable-solutions (DOT) net[/email]

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Eugene Gershnik
Guest





PostPosted: Sat Jan 22, 2005 6:50 pm    Post subject: Re: Is auto_ptr_ref still needed? Reply with quote

[email]kanze (AT) gabi-soft (DOT) fr[/email] wrote:
Quote:
Seriously, of course, this is probably not a bug. Originally,
C++ did allow binding a temporary to a non-const reference, and
g++ is the only compiler I use today that doesn't still allow
it. Of course, the others do give a warning, along the lines of
"anachronism", or "obsolete".

While I generally encourage support for older code, I'm not sure
how necessary this is (or should be).

One real benefit of this "extension" is that it allows one to write in
"constless" C++, that is in a language that looks exactly like C++ without
word const anywhere. For somebody that has to interact with large body of
old code or just doesn't like const-correctness this could be a blessing.
The alternative is to heavily season the code with const_casts or C casts
which people understandably dislike.
Const and const correctness are still not quite common in Win32 world. The
system API itself is mostly const-ignorant and there are quite a few people
who consider dealing with const correctness a waste of their time[1]. Note
the telling absence of const in the new .NET world. All of this probably
explains why the old rule is the default in VC. In any case, VC does produce
a warning on a high enough warning level which is all one needs to write
portable code.

--
Eugene

[1] - I am tempted to abandon const every time I meet its interactions with
templates ;-)



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
KCs
Guest





PostPosted: Mon Jan 24, 2005 10:38 pm    Post subject: Re: Is auto_ptr_ref still needed? Reply with quote

It's very interesting what you wrote about constless C++ and .NET. I
read once an interview with Anders Hejlsberg about const in .NET at:
http://www.artima.com/intv/choices.html.
Now my questions are:
- if you write new code in C++ and use MFC and STL is it reasonable to
leave MS extensions on?
- with MS extensions off how the new interface of auto_ptr proposed by
Rani Sharoni at
http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#463 (thanks
to David Abrahams) can be compiled. More precisely not only the
interface, but also it's usage in function parameters and return
values.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.