I don't have to tell you...

H

Howard Beale

I don't have to tell you C++ is bad. Everybody knows C++ is bad. It's an
OOP language. Everybody's tired of the STL or scared of using templates. An
hour of coding accomplishes five minutes worth, software companies are
going bust, programmers keep a resume in the desk drawer. Shitty javascript
is running wild on the web and there's nobody anywhere who seems to know
how to code, and there's no end to it. We know iterators are unfit to use
and class heirarchies never work the way they're supposed to, and we sit
watching porn while some blogger tells us that today there were fifteen new
half-ass workarounds for std::vector and sixty-three new things you can't
do with a template, as if that's the way it's supposed to be. We know OOP
is bad -- worse than bad. It's crazy. It's like every programmer everywhere
has gotten lazy, so we don't even attempt to write efficient code anymore.
We sit at the office, and slowly the technology we are creating is getting
crappier, and all we say is, "Please, at least leave our PCs alone. Let me
have my Commodore 64 emulator and my fractals and my original DOOM and I
won't say anything. Just leave us alone." Well, I'm not gonna leave you
alone. I want you to get mad! I don't want you to write a new container
library. I don't want you to start using C# or D. I don't want you to write
to the C++0x working group because I wouldn't know what to tell you to
write.

....

I want you to get up right now, get up, go to your windows, open them and
stick your head out and yell, "I'm as mad as hell and I'm not going to take
C++ anymore!" Things have got to change. But first, you've gotta get mad!



That was kind of fun. But seriously, you should be mad at C++ because it
sucks.
 
C

carl

Howard Beale said:
I don't have to tell you C++ is bad. Everybody knows C++ is bad. It's an
OOP language. Everybody's tired of the STL or scared of using templates.
An
hour of coding accomplishes five minutes worth, software companies are
going bust, programmers keep a resume in the desk drawer. Shitty
javascript
is running wild on the web and there's nobody anywhere who seems to know
how to code, and there's no end to it. We know iterators are unfit to use
and class heirarchies never work the way they're supposed to, and we sit
watching porn while some blogger tells us that today there were fifteen
new
half-ass workarounds for std::vector and sixty-three new things you can't
do with a template, as if that's the way it's supposed to be. We know OOP
is bad -- worse than bad. It's crazy. It's like every programmer
everywhere
has gotten lazy, so we don't even attempt to write efficient code anymore.
We sit at the office, and slowly the technology we are creating is getting
crappier, and all we say is, "Please, at least leave our PCs alone. Let me
have my Commodore 64 emulator and my fractals and my original DOOM and I
won't say anything. Just leave us alone." Well, I'm not gonna leave you
alone. I want you to get mad! I don't want you to write a new container
library. I don't want you to start using C# or D. I don't want you to
write
to the C++0x working group because I wouldn't know what to tell you to
write.

...

I want you to get up right now, get up, go to your windows, open them and
stick your head out and yell, "I'm as mad as hell and I'm not going to
take
C++ anymore!" Things have got to change. But first, you've gotta get mad!



That was kind of fun. But seriously, you should be mad at C++ because it
sucks.

Hehe

I'm as mad as hell and I'm not going to take C++ anymore!!


:)
 
B

Brian

I don't have to tell you C++ is bad. Everybody knows C++ is bad. It's an
OOP language. Everybody's tired of the STL or scared of using templates. An
hour of coding accomplishes five minutes worth, software companies are
going bust, programmers keep a resume in the desk drawer. Shitty javascript
is running wild on the web and there's nobody anywhere who seems to know
how to code, and there's no end to it. We know iterators are unfit to use
and class heirarchies never work the way they're supposed to, and we sit
watching porn while some blogger tells us that today there were fifteen new
half-ass workarounds for std::vector and sixty-three new things you can't
do with a template, as if that's the way it's supposed to be. We know OOP
is bad -- worse than bad. It's crazy. It's like every programmer everywhere
has gotten lazy, so we don't even attempt to write efficient code anymore..

I disagree with most of this, but think there's some truth to that
last sentence. A lot of programmers got lazy and stopped paying
attention to efficiency issues.


I want you to get up right now, get up, go to your windows, open them and
stick your head out and yell, "I'm as mad as hell and I'm not going to take
C++ anymore!" Things have got to change. But first, you've gotta get mad!

That was kind of fun.  But seriously, you should be mad at C++ because it
sucks.

I don't claim it is great, but that it is better than the other well-
known languages.


Brian Wood
http://webEbenezer.net
 
J

James Kanze

I don't claim it is great, but that it is better than the
other well- known languages.

C++ is bad. It's just that all of the reasonable alternatives
are worse. (Some one---I don't know who---originally said that
about democracy.)
 
S

Saeed Amrollahi

I disagree with most of this, but think there's some truth to that
last sentence.  A lot of programmers got lazy and stopped paying
attention to efficiency issues.





I don't claim it is great, but that it is better than the other well-
known languages.

Brian Woodhttp://webEbenezer.net

Hi Brian

I am with you.
About laziness, you are right. I think about that a lot.
A lot of people in my company and in my vicinity (Tehran) are lazy in
programming.
Apparently, it is world-wide :( I suspect, we will have programmers
like Ken Thompson or
Brian Kernighan in near future.

Regards,
-- Saeed Amrollahi
 
M

Mick

James said:
C++ is bad. It's just that all of the reasonable alternatives
are worse. (Some one---I don't know who---originally said that
about democracy.)
Churchill, Something like: "Democracy is the worst possible system of
government, apart from all the others we have tried."
 
H

Howard Beale

James said:
C++ is bad. It's just that all of the reasonable alternatives
are worse. (Some one---I don't know who---originally said that
about democracy.)


My personal thoughts (OP here):

Machine code on punch cards was acceptable until something better came
along.

Assembly language added readability and maintainability and was less
error-prone. Assembly language was acceptable until something better
came along.

FORTRAN added readability and maintainability and was less error-prone.

The step from FORTRAN to C was different. C provided more explicit
dealings with pointers, data structures, etc, and was targeted more
towards computer scientists than mathematicians. FORTRAN was (and
remains) a good choice for pure number crunching, e.g. benchmarking
supercomputers. But with C, it became apparent that there was more to
programming than number crunching, and C was the best choice for general
programming.

Up to here, we're still talking about baby steps. Each step just gives
the programmer a little more convenience and a little more power, but we
really haven't gone very far at all from where we started -- machine
code. The translation from C to machine code is very "thin."

The step from C to C++ is not a step at all, it's a giant leap of faith.
C++ is a paradigm shift more than it is a successor to C. In fact, I
believe that the main problems with C++ are a result of its attempt to
still "be" C for the most part, as opposed to just becoming something
entirely new. It attempts to bring OOP to C by just adding a few
keywords and angle brackets here and there.

The translation from C++ to machine code is NOT thin. Things are hidden
from the programmer and, worse, are beyond his or her control. And many
of these are really significant. In what order are constructors and
destructors called? Answer - in whatever order ANSI/ISO chooses to call
them, and you'll never know just by looking at your code, and you'll
never be able to change it if it doesn't suit you. Does it matter? Yes
- the choice that was made means that you should never call virtual
functions from a constructor or destructor, even though the language
will allow you to do so with no warning, just incorrect behavior. On
the other hand, you had better remember to make your destructors virtual
(in some cases), or you'll have memory leaks for some reason that is
entirely invisible when looking at your code. What does a template
really do? Answer - it creates a LOT of code behind the scenes that
you'll never see, but it's purely a compile-time construct, so don't
expect to do any truly elegant polymorphic type things with them.
Operator overloading looks cool at first glance, is it useful? Answer -
in almost every case, NO.

These are just some examples, and some C++ experts are fine with them.
There are ways to work around the shortcomings, usually at the expense
of readability or efficiency.

But my feeling is that class hierarchies, templates, operator
overloading, etc, are the only things that C++ really brings to the
table, and these are the things that don't work like they should! I
might as well use C and have tables of function pointers wherever that
approach is more efficient than a switch statement. Encapsulation and
information hiding? Just write a clean and well documented API.

I don't believe that C is the last step in the evolution of programming
languages and that everything afterward has been a mistake. But I do
feel that C++ was not the right answer.
 
A

Alf P. Steinbach

* Howard Beale:
In what order are constructors and
destructors called? Answer - in whatever order ANSI/ISO chooses to call
them, and you'll never know just by looking at your code, and you'll
never be able to change it if it doesn't suit you. Does it matter? Yes
- the choice that was made means that you should never call virtual
functions from a constructor or destructor, even though the language
will allow you to do so with no warning, just incorrect behavior.

Jeez, where do you pick up such misconceptions?



Cheers & hth.,

- Alf
 
H

Howard Beale

Alf said:
Jeez, where do you pick up such misconceptions?

What's miconceived?

C++ FAQ [23.5]:
- "When my base class's constructor calls a virtual function on its this
object, why doesn't my derived class's override of that virtual function
get invoked?"
http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.5

http://www.artima.com/cppsource/nevercall.html
- "Never Call Virtual Functions during Construction or Destruction"


One could argue that it's good thing for C++ not to allow this, but I'd
simply point out that more recent languages don't have a problem with it:

http://www.andymcm.com/csharpfaq.htm#3.9

Yes, I know that it's recommended (in C#) not to call virtual functions
from constructors / destructors, but it is supported and will work the way
you expect. The danger is just that someone else overriding your virtual
function may unknowingly alter the behavior of construction / destruction.
 
A

Alf P. Steinbach

* Howard Beale:
Alf said:
Jeez, where do you pick up such misconceptions?

What's miconceived?

C++ FAQ [23.5]:
- "When my base class's constructor calls a virtual function on its this
object, why doesn't my derived class's override of that virtual function
get invoked?"
http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.5

This is good. It's the official C++ FAQ. Since you're using it as authority I
mention that some of that stuff further down originated with me. :)

http://www.artima.com/cppsource/nevercall.html
- "Never Call Virtual Functions during Construction or Destruction"

This, however, is total bullshit.

In the technical sense, that is.

Thanks for pointing it out!

One could argue that it's good thing for C++ not to allow this, but I'd
simply point out that more recent languages don't have a problem with it:

http://www.andymcm.com/csharpfaq.htm#3.9

On the contrary, Java and C# have very dangerous problems with virtual calls
from constructors.

It's one of the most common bugs in Java applications (you can get a subclass
method invoked before the subclass object has been initialized).

In C++ virtual calls from constructors are safe, with one exception, namely a
call of a pure virtual.

The FAQ explains how it works in C++, but just if you don't want to spend on
time on finding that:

In C++, during a constructor of type T, the '*this' object is of most derived
type (dynamic type) T -- so everything works as the author of class T expects,
no matter whether this constructor call originated from some subclass.

Yes, I know that it's recommended (in C#) not to call virtual functions
from constructors / destructors, but it is supported and will work the way
you expect. The danger is just that someone else overriding your virtual
function may unknowingly alter the behavior of construction / destruction.

It's a bit more dangerous that in Java/C#; see above.


Cheers & hth.,

- Alf
 
B

Balog Pal

Alf P. Steinbach said:
Jeez, where do you pick up such misconceptions?

What's miconceived?

C++ FAQ [23.5]:
- "When my base class's constructor calls a virtual function on its this
object, why doesn't my derived class's override of that virtual function
get invoked?"
http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.5

This is good. It's the official C++ FAQ. Since you're using it as
authority I mention that some of that stuff further down originated with
me. :)
Mega-LOL.
http://www.artima.com/cppsource/nevercall.html
- "Never Call Virtual Functions during Construction or Destruction"

This, however, is total bullshit.

It isn't. It's Item#9 form EC++, explains well what is going on really, with
summary "Don't call virtual functions during construction or destruction,
because such calls will never go to a more derived class than that of the
currently executing constructor or destructor."

What quoted above is the item title -- that shall not be used as replacement
of the item content itself. :-o

Do you think a guideline book should add "unless you hit an exception" or
"unless you know better"?
In C++ virtual calls from constructors are safe, with one exception,
namely a call of a pure virtual.

Isn't it also safely call terminate() ?
 
A

Alf P. Steinbach

* Balog Pal:
Alf P. Steinbach said:
Jeez, where do you pick up such misconceptions?

What's miconceived?

C++ FAQ [23.5]:
- "When my base class's constructor calls a virtual function on its
this object, why doesn't my derived class's override of that virtual
function get invoked?"
http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.5

This is good. It's the official C++ FAQ. Since you're using it as
authority I mention that some of that stuff further down originated
with me. :)
Mega-LOL.
http://www.artima.com/cppsource/nevercall.html
- "Never Call Virtual Functions during Construction or Destruction"

This, however, is total bullshit.

It isn't. It's Item#9 form EC++,

I don't care about the messenger. The message is bullshit. Really bad advice.
FUD. Even in the context of programming for constrained embedded systems
(there's no connection).


Cheers & hth.,

- Alf
 
B

Balog Pal

Alf P. Steinbach said:
I don't care about the messenger. The message is bullshit. Really bad
advice. FUD. Even in the context of programming for constrained embedded
systems (there's no connection).

I'm confused. Please quote me the part of the message which fits the
description, or elaborate.

Also, which are the situations, when you actually want to actively call
virtuals (the implicit dtor call doesn't count) in the mentioned places? I
failed to think up a sensible example.
 
A

Alf P. Steinbach

* Balog Pal:
I'm confused. Please quote me the part of the message which fits the
description, or elaborate.

Every part of the quoted part is meaningless FUD.

So, I haven't looked at the rest. :)

Also, which are the situations, when you actually want to actively call
virtuals (the implicit dtor call doesn't count) in the mentioned places?

Quite a lot of code does that, though not the with motivation that you describe. :)

The point is that you don't have to care whether the methods are virtual or not.

In C++ it's safe to call them anyway.

I failed to think up a sensible example.

Actually I fail to come up with any simple example where I'd use a virtual
member for anything.

But as an abstract example, if a base class has a non-virtual method foo(), that
calls a virtual method bar(), and your derived class T overrides bar(), then in
your T constructor you can call foo and foo's call of bar() ends up in T::bar.

It's a not uncommon scenario. The mentioned bugs in Java programs are mainly due
to this scenario occurring often in actual code. In C++ it's no problem. :)


Cheers & hth.,

- Alf
 
H

Howard Beale

Alf said:
* Balog Pal:

Every part of the quoted part is meaningless FUD.

So, I haven't looked at the rest. :)



Quite a lot of code does that, though not the with motivation that you
describe. :)

The point is that you don't have to care whether the methods are
virtual or not.

In C++ it's safe to call them anyway.


I'm sorry, I can't spot anywhere in this thread where you point out
what's wrong with the original claim... which is supported by the FAQ
(which you apparently helped write) and that article (which I chose
simply because it was the first hit returned by Google on the subject).

If you have a base class "shape" and derived classes "square,"
"circle," and "rectangle," and declare this in shape:

virtual std::string GetName() { return "shape"; }
virtual float GetArea() { return 0; }
virtual ~shape()
{
cout << "Just destroyed a " << GetName()
<< " with area " << GetArea() << endl;
}

and if your circle class has this:

std::string GetName() { return "circle"; }
float GetArea() { return 3.14f * r * r; }

The output when a circle is deleted will be:

"Just destroyed a shape with area 0"

And the reason for this behavior is exactly what I originally said.
 
G

Gert-Jan de Vos

I'm sorry, I can't spot anywhere in this thread where you point out
what's wrong with the original claim...  which is supported by the FAQ
(which you apparently helped write) and that article (which I chose
simply because it was the first hit returned by Google on the subject).

If you have a base class "shape" and derived classes "square,"
"circle," and "rectangle," and declare this in shape:

  virtual std::string GetName() { return "shape"; }
  virtual float GetArea() { return 0; }
  virtual ~shape()
  {
    cout << "Just destroyed a " << GetName()
    << " with area " << GetArea() << endl;
  }

and if your circle class has this:

  std::string GetName() { return "circle"; }
  float GetArea() { return 3.14f * r * r; }

The output when a circle is deleted will be:

  "Just destroyed a shape with area 0"

And the reason for this behavior is exactly what I originally said.

I'm not sure what your "original claim" is. I see mostly a rant and
some random not-supported claims about C++ features. Anyway, your
example makes perfect sense:

Your shape base class destructor reports that it just destroyed a
concrete shape. It did, therefore the concrete shape itself does not
exist anymore by the time you get there and there is nothing it can
do. C++ protects you here by making the dynamic behavior of your shape
now that of shape itself, that's all you have. Whether you like it or
not.
 
J

Joshua Maurice

Now, I know you're just trolling, but I'm easily baited.

I don't have to tell you C++ is bad. Everybody knows C++ is bad. It's an
OOP language.
Everybody's tired of the STL or scared of using templates.

Really? I like the STL for the most part. It saves a huge amount of
time that I would otherwise have to spend maintaining my own container
library, and actual implementations are probably much more efficient
than anything I could write, partly because the better interfaces (aka
iterators), and partly because you have programmers who read the
journals on the latest techniques on algorithms.
An hour of coding accomplishes five minutes worth, software companies
are going bust, programmers keep a resume in the desk drawer.

I don't know where you're pulling this from. Your ass maybe? I'm
pretty sure there are many, many, successful companies who still use C+
+. Some might argue that Java et al are replacing C++, but there are
still many domains which C++ will be used for a long time, eg: games
and other performance critical code.
We know iterators are unfit to use

What? I know of some people who complain that ranges should have been
used instead, but I assume this is not the argument you are making.
What is your alternative to the easy-to-use iterators which allow
generic algorithms on disparate kinds of containers? What makes
iterators unfit to use?
class heirarchies never work the way they're supposed to,

What?
 
A

Alf P. Steinbach

* Howard Beale:
I'm sorry, I can't spot anywhere in this thread where you point out
what's wrong with the original claim... which is supported by the FAQ
(which you apparently helped write) and that article (which I chose
simply because it was the first hit returned by Google on the subject).


You made several factually incorrect claims, as I count it four of them in the
single paragraph of yours that I quoted in my first response:

* Howard Beale:
In what order are constructors and destructors called? Answer - in
whatever order ANSI/ISO chooses to call them, and [1] you'll never know
just by looking at your code, and [2] you'll never be able to change it
if it doesn't suit you. Does it matter? Yes - the choice that was
made means that [3] you should never call virtual functions from a
constructor or destructor, even though [4] the language will allow you to
do so with no warning, just incorrect behavior.

To which of these four incorrect claims (if any) are you referring?

None of them are supported by the FAQ.

By the way, the FAQ has many contributors. Many of the regulars in this group
have contributed to it. But it's penned exclusively by Marshall Cline. :)

If you have a base class "shape" and derived classes "square,"
"circle," and "rectangle," and declare this in shape:

virtual std::string GetName() { return "shape"; }
virtual float GetArea() { return 0; }
virtual ~shape()
{
cout << "Just destroyed a " << GetName()
<< " with area " << GetArea() << endl;
}

and if your circle class has this:

std::string GetName() { return "circle"; }
float GetArea() { return 3.14f * r * r; }

The output when a circle is deleted will be:

"Just destroyed a shape with area 0"

And the reason for this behavior is exactly what I originally said.

This illustrates that calling virtuals in C++ destructors is safe and yields a
well-known predictable effect. When the 'shape' destructor executes there's no
longer any 'circle' sub-object. It would be generally undefined behavior if a
call was made down on that non-existing sub-object, and C++ guarantees that that
doesn't happen for an ordinary virtual call: the 'shape' programmer knows
exactly what will happen, and does not have to worry about any 'circle' class.


Cheers & hth.,

- Alf
 
B

Balog Pal

Alf P. Steinbach said:
Every part of the quoted part is meaningless FUD.

So, I haven't looked at the rest. :)

And doing so you flushed the baby with the bathwater. FUD is something that
puts down a claim and either not include rationale at all or creates a phony
one. You shouldn't address content such without reading it.
The point is that you don't have to care whether the methods are virtual
or not.
In C++ it's safe to call them anyway. ....
But as an abstract example, if a base class has a non-virtual method
foo(), that calls a virtual method bar(), and your derived class T
overrides bar(), then in your T constructor you can call foo and foo's
call of bar() ends up in T::bar.

It's a not uncommon scenario. The mentioned bugs in Java programs are
mainly due to this scenario occurring often in actual code. In C++ it's no
problem. :)

It *IS* a problem. One you appear to miss entirely, or turn a blind eye.

The problem is not of the nature you argue against. Technically the call
works, and what it does is fully defined. And what happens (IMO) makes more
sense too, than say in java.

The problem is a human one -- when calls to virtuals are done, directly or
indirectly, the expectation is they end up in the most derived object. In
the real-life and not the technical sense. People are (appear) just not
aware that in ctor and dtor different rules apply, and expect the code just
work by magic -- as it does in every other context.

The thing is on the FAQ is exactly for that: too many tried and got
surprized. Or even call 'foul' for calling the 'wrong' function. The
fact that we know tha language rules, and can apply sense to say what is the
'right' function technicly will NOT make it correct in the code -- that
*expects* a different behavior. That expectation will not go away by
deducing it as like-impossible to implement either.
It's a not uncommon scenario. The mentioned bugs in Java programs are
mainly due to this scenario occurring often in actual code. In C++ it's no
problem. :)

In java the manifest problem is dealing with half-baked object in the
expected function.
In C++ it manifests by arriving in Self::foo(). What is way easier to
discover and rearrange the design.

The usual rearrangement is to pass the work up, and make the result of the
former virtual call a parameter of the ctor...
And for dtors you sigh, and copy the code in the derived dtors...

In both cases the call to virtual gets removed from the code, like obeying
the "don't". :)
 
A

Alf P. Steinbach

* Balog Pal:
And doing so you flushed the baby with the bathwater. FUD is something
that puts down a claim and either not include rationale at all or
creates a phony one. You shouldn't address content such without reading
it.


It *IS* a problem. One you appear to miss entirely, or turn a blind eye.

The problem is not of the nature you argue against. Technically the
call works, and what it does is fully defined. And what happens (IMO)
makes more sense too, than say in java.

The problem is a human one -- when calls to virtuals are done, directly
or indirectly, the expectation is they end up in the most derived
object.

The incompetence of experienced people is a problem with no known solution.

You say that at least some people, and I assume that you mean experienced ones,
expect the language to behave in a nonsensical way, like some other language
they're familiar with.

And it seems that you're implicitly arguing that because of their nonsensical
expectation the safe behavior is a problem.

That since they practically can't be made competent, the language should be
dumbed down to their level, removing safety features they fail to understand.

Hello.

In the real-life and not the technical sense. People are
(appear) just not aware that in ctor and dtor different rules apply, and
expect the code just work by magic -- as it does in every other context.

The thing is on the FAQ is exactly for that: too many tried and got
surprized. Or even call 'foul' for calling the 'wrong' function.

No, the FAQ is mainly for novices.

A novice may expect C++ to work like some other language, e.g. like Java.

An experienced C++ programmer who expects that, however, is incompetent.

The fact that we know tha language rules, and can apply sense to say
what is the 'right' function technicly will NOT make it correct in the
code -- that *expects* a different behavior. That expectation will not
go away by deducing it as like-impossible to implement either.

I have on some occasions dumbed down code so that it "should" be grokkable even
by idiots.

But I no longer believe that that is a good idea, I now believe that what I with
good intentions did was actually "evil".

The incompetents remain as confused and dazed as ever, and anyone competent who
doesn't labor from a similar misconception that incompetents can be accomodated,
will just think that the one who wrote the code was in that category -- or
waste time trying to figure out why things weren't done in more idiomatic ways.

In java the manifest problem is dealing with half-baked object in the
expected function.
In C++ it manifests by arriving in Self::foo(). What is way easier to
discover and rearrange the design.

You don't want to rearrange the correctly working C++ code.

So, C++: zero time.

Fixing the Java code takes some time.

The usual rearrangement is to pass the work up, and make the result of
the former virtual call a parameter of the ctor...
And for dtors you sigh, and copy the code in the derived dtors...

This doesn't make sense. It seems you have some problem and some particular
based-on-misconceptions non-working solution to that problem in mind. Don't
blame that on the language: blame it on a fixation on a non-working solution.

Not knowing the exact problem I can't help you with that, however.

In both cases the call to virtual gets removed from the code, like
obeying the "don't". :)

What you're saying seems to be that you have suffered from the "C++ works like
Java" misconception, and fixed that by removing calls that you believed would
end up in a derived class.

Well that's not something to blame C++ for.

Rather, in that case you learned something new and better. :)


Cheers & hth.,

- Alf
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,763
Messages
2,569,562
Members
45,038
Latest member
OrderProperKetocapsules

Latest Threads

Top