New to C++

P

Pinnerite

I'm actually trying to get back in after many years stuck in the past.
Below is code from a test routine intended to solve my technical mistakes:

#include <iostream>
#include <string>

using namespace std;

int main(int argc, char *argv[])
{
string myfilename = "";
string getfilename(); // error message 1

string getfilename(myfilename); // error message 2

return 0;
}

string getfilename(string myfilename)
{
myfilename = "success";

return myfilename;
}


Error messages
1) std::string getfilename' redeclared as different kind of symbol
2) error: previous declaration of 'std::string getfilename()'


I would be grateful for corrections. My tutorial doesn't seem to cover it.
 
S

Stuart

I'm actually trying to get back in after many years stuck in the past.
Below is code from a test routine intended to solve my technical mistakes:

#include <iostream>
#include <string>

using namespace std;

int main(int argc, char *argv[])
{
string myfilename = "";
string getfilename(); // error message 1

string getfilename(myfilename); // error message 2

return 0;
}

string getfilename(string myfilename)
{
myfilename = "success";

return myfilename;
}


Error messages
1) std::string getfilename' redeclared as different kind of symbol
2) error: previous declaration of 'std::string getfilename()'


I would be grateful for corrections. My tutorial doesn't seem to cover it.

Just to add what others have already posted: I think that this kind of
trap could be easily avoided with a better error description. The line
that is indicated by "// error message 1" is almost always a mistake. I
have never ever seen anyone using such a thing in my ten years of
prefessional C++ programming. On the other hand, I have seen lots of
people that fell for this.

So in my humple opinion the error message 1 should be something "The
function declaration 'string getfilename();' is redeclaring <something>.
Did you really mean to declare a function?"

Regards,
Stuart
 
V

Victor Bazarov

I'm actually trying to get back in after many years stuck in the past.
Below is code from a test routine intended to solve my technical
mistakes:

#include <iostream>
#include <string>

using namespace std;

int main(int argc, char *argv[])
{
string myfilename = "";
string getfilename(); // error message 1

string getfilename(myfilename); // error message 2

return 0;
}

string getfilename(string myfilename)
{
myfilename = "success";

return myfilename;
}


Error messages
1) std::string getfilename' redeclared as different kind of symbol
2) error: previous declaration of 'std::string getfilename()'


I would be grateful for corrections. My tutorial doesn't seem to cover
it.

Just to add what others have already posted: I think that this kind of
trap could be easily avoided with a better error description. The line
that is indicated by "// error message 1" is almost always a mistake. I
have never ever seen anyone using such a thing in my ten years of
prefessional C++ programming. On the other hand, I have seen lots of
people that fell for this.

You seem to miss a simple possibility. It's a function declaration, but
is without any arguments specified - like C90 (and K&R C) used to do.
It means "any arguments are OK".

In C++ empty parens means "no arguments shall be given". That's the
main difference here.
So in my humple opinion the error message 1 should be something "The
function declaration 'string getfilename();' is redeclaring <something>.
Did you really mean to declare a function?"

I think that's exactly what OP did (or rather intended to do). Old C
habits die hard.

V
 
P

Pinnerite

Stuart said:
I'm actually trying to get back in after many years stuck in the past.
Below is code from a test routine intended to solve my technical
mistakes:

#include <iostream>
#include <string>

using namespace std;

int main(int argc, char *argv[])
{
string myfilename = "";
string getfilename(); // error message 1

string getfilename(myfilename); // error message 2

return 0;
}

string getfilename(string myfilename)
{
myfilename = "success";

return myfilename;
}


Error messages
1) std::string getfilename' redeclared as different kind of symbol
2) error: previous declaration of 'std::string getfilename()'


I would be grateful for corrections. My tutorial doesn't seem to cover
it.

Just to add what others have already posted: I think that this kind of
trap could be easily avoided with a better error description. The line
that is indicated by "// error message 1" is almost always a mistake. I
have never ever seen anyone using such a thing in my ten years of
prefessional C++ programming. On the other hand, I have seen lots of
people that fell for this.

So in my humple opinion the error message 1 should be something "The
function declaration 'string getfilename();' is redeclaring <something>.
Did you really mean to declare a function?"

Regards,
Stuart

Thank you for all your advice. It is at least 25 years since I touched 'C'
but I have continued to maintain a program written in Clipper started over
20 years ago, that uses 'C' like structures and presentation. Accordingly I
am wary of making assumptions.

The routine is being tested in the QT Creator IDE and though the error
messages seem arcane to the inexperienced eye, I can see that they are
beginning to make sense.

Please excuse me though if I come back with yet another bloomer. It will not
be for want of trying to find solutions myself.

Interestingly Mike McGrath's book doesn't show a single illustration of one
function calling another.

Regards

Alan
 
S

Stuart

On 12/17/2012 Stuart wrote:
[snip]
You seem to miss a simple possibility. It's a function declaration, but
is without any arguments specified - like C90 (and K&R C) used to do. It
means "any arguments are OK".

In C++ empty parens means "no arguments shall be given". That's the
main difference here.


I think that's exactly what OP did (or rather intended to do). Old C
habits die hard.

I'm so happy that I was born so late that I never had to have use C.
OTOH, I am also happy that I wasn't born too late so that the only thing
I could learn at university was Java, either. Apparently I have to
consider myself quite a lucky guy ...

Stuart
 
R

Rui Maciel

Stuart said:
I'm so happy that I was born so late that I never had to have use C.
OTOH, I am also happy that I wasn't born too late so that the only thing
I could learn at university was Java, either. Apparently I have to
consider myself quite a lucky guy ...

C isn't as bad as you made it out to be. In fact, it's actually quite nice,
particularly when considering how other languages, such as C++, ended up
being so complex and hard to master. It might not be perfect, but what is?


Rui Maciel
 
S

Swifty

Consider yourself lucky you never had to use COBOL

Here in the UK, I was taught that this is one of the reasons for the
National Lottery, as demonstrated in the proforma resignation letter:

"... I won the Jackpot on the National Lottery, so you can stuff your
COBOL programs..."

Such dreams were commonplace during late 1999 when the COBOL programmers
were checking for Y2K bugs.

P.S. I only ever found one Y2K bug in my own code, so I changed it into
a Y3K bug as the simplest solution.

P.P.S One of my colleagues actually did win the jackpot, and a rollover
to boot. His VoiceMail message said simply "Leave a message after the
tone; I'll never get back to you. I won Saturday's rollover jackpot, and
by the time you hear this, I'll be in the Bahamas"
 
P

Paul Rubin

Juha Nieminen said:
I think it's a shame that textbooks and tutorials teach such a bad habit.

See also B. Stroustrup, The C++ Programming Language (special edition),
p. 47. Admittedly he doesn't exactly recommend the practice.
 
Ö

Öö Tiib

I think it's a shame that textbooks and tutorials teach such a bad habit.

Yes. Majority of examples do it. Same with boost. Most boost examples
have using directive in them. Rare (like boost::program_options)
examples use namespace aliases. Next to never you can find using
directive for the thing demonstrated in example.

The authors say (when asked about that practice) that it makes the
examples shorter and so simpler to read. I do not think that they
use using directive in their own works. That is apparently yet
another of the bear traps that our community provides to the poor
novices.
 
Ö

Öö Tiib

In the vast majority of cases they make the examples "shorter" by making
them longer? (After all, you need to write "std::" at least 5 times in
order to make the program longer than if you had used "using namespace std;"
instead.

That is what they say. :( 5 is actually typically reached, most
examples use stream i/o:

std::cout << "octal 42: " << std::eek:ct << 42 << '\n'
<< "decimal 42: " << std::dec << 42 << '\n'
<< "hexadecimal 42: " << std::hex << 42 << std::endl;

However ... not sure, why they believe that it ^ is oh so long
and complex to read.
 
T

Tobias Müller

Juha Nieminen said:
I think it's a shame that textbooks and tutorials teach such a bad habit.

Actually, I don't understand, why this flame comes up each and every time
someone writes "using namespace std;".

I can't see why this should be harmful in case of namespace std. Sure, for
other namespaces it's a different story.
If std::string is for strings what int is for integers, then why should it
be harmful to use it unqualified? You can still use any other string
classes qualified.

Tobi
 
Ö

Öö Tiib

Actually, I don't understand, why this flame comes up each and every time
someone writes "using namespace std;".

I can't see why this should be harmful in case of namespace std. Sure, for
other namespaces it's a different story.

When someone uses convenient short name that happens is also in std
namespace (like 'thread' or 'list' or 'ref') then things start to clash
and who the poor noob asks about strange error messages that he had
stared at for last two hours? Me of course. Sure, it is harmful he sat
and stared there *and* it is harmful since more important things
had to wait while I solved such nonsense issue.
If std::string is for strings what int is for integers, then why should it
be harmful to use it unqualified? You can still use any other string
classes qualified.

String may also (depending on problem domain) mean:
* a cord usually used to bind, fasten, or tie
* a plant fiber
* the gut, wire, or nylon cord of a musical instrument
* the action of lagging for break in billiards
etc. etc.

So you techically say the applications for such domains should use names
like 'cord_used_to_tie' instead of 'string' and 'string' unqualified
instead of 'std::string'? Or ... if it is really a domain where string
means also 'line of characters' then why not to import string into
domain namespace with 'using std::string;' and so leave 'std::thread'
still unimported?

Whole point of namespace std and namespaces in general seems to be is
apparently too dim for so lot of people. First they use "using namespace"
a lot. Then they get clashes. Then they fall back to age of in-name
qualifiers.

Result: the 30+ character names are not too uncommon and the code base
looks as an inelegant pile of bloat that it is.
 
J

Jorgen Grahn

When someone uses convenient short name that happens is also in std
namespace (like 'thread' or 'list' or 'ref') then things start to clash

Or copy, find, read, ...

Perhaps people who don't mind this are people who choose long and
convoluted names, like we used to do in C? Or use camelCase
conventions? Personally I tend to come up with function names which
look like the ones in namespace std, so I almost always spell out the
std::.

/Jorgen
 
B

Balog Pal

Shouldn't be so much different. IME namespaces appear high on the 'most
abused feature' list. They were introduced so we can handle the clash
problem with 3rd party stuff in some sensible way, that is not in our
control.

Then I see it used to add a ton of noise to our code, and to
deliberately create clashes just to force that noise everywhere.

Another antipattern I see probably comes from java worls in form of
nested, even deeply nested namespaces.

In a project I worked a few years ago, for 40KLOC of code there were
~300 namespaces, at least 3 level deep, with average name count below 5.
And despite heavy use using directives the code was infested with 20+
letter prefixes making it utterly unreadable.

Fortunately no one objected my motion to eliminate all the namespaces in
a single refactoring step. :)
Or copy, find, read, ...

Perhaps people who don't mind this are people who choose long and
convoluted names, like we used to do in C? Or use camelCase
conventions? Personally I tend to come up with function names which
look like the ones in namespace std, so I almost always spell out the
std::.

I definitely would not pass on a review a homegrown class named 'list'.
Honestly can't even imagine an explanation why would one present it so.
 
T

Tobias Müller

Juha Nieminen said:
Because teaching people out of their bad habits is a good thing.
*Not* pointing out those bad habits is not going to help anybody.


What's the point in having namespaces in the first place if they are not
going to be used?

What's the point if having namespaces over simple prefixes, if you never
use its members unqualified?
The whole idea with namespaces is to avoid name collisions. And this is
not just theoretical. There have been actual concrete projects that have
become broken because they used, for example, the name "shared_ptr"
unqualified from the Boost project, after the compiler updated to the
new C++ standard (which, surprise surprise, these projects also used
with unqualified names.)

I never suggested using boost namespace unqualified, just namespace std.
But I still don't see why this is dangerous. It's clear that switching to a
new language standard may break some code and it's also easy to fix. It
gives you a compliation error, not a runtime crash.
Also, using the std:: prefix increases readability and makes the code
easier to understand. You can spot the usages of standard utilities with
a quick visual scan, without even having to decipher the code in detail.

std should be used everywhere and as much as possible.
The prefix can be really informative on its own right. For example, suppose
you see this line of code:

if(equal(a, b, c))

what does that line tell to you? Not much, really. A function named
'equal', which might be defined *somewhere*, is being called with some
parameters. We can't really say where that function might be defined
(is it local to the current compilation unit, is it an extern function,
is it in some other library, is it a standard function...?) nor do we
know anything about those parameters.

So then you are probably also using hungarian notation? It really would be
a shame if you could not read every single detail out of a class or
variable name.
In those rare cases where I don't recognize the use of a std utility I rely
on Intellisense (or similar features in other IDEs).
But now, imagine that the line had been like this instead:

if(std::equal(a, b, c))

This is a whole lot more informative. Now we know *immediately* that it's
a call to a standard function, and we also know what the parameters are
(they are iterators or pointers). And even if you didn't know what
std::equal() does, at least you know where to look for that info.

Actually I'm quite sure that you don't use hungarian notation. If someone
uses it here, it often provokes similar comment as yours.
Still, the reason for using qualified namespaces and hungarian notation is
very similar.

I do use hungarian notation sometimes where the type of a variable is not
expressive enough, for example char*: pChar for generic pointer vs.
szString for zero terminated string.
I use qualified namespaces alot, but I can also see the use of unqualified
names.

Tobi
 
T

Tobias Müller

Öö Tiib said:
When someone uses convenient short name that happens is also in std
namespace (like 'thread' or 'list' or 'ref') then things start to clash
and who the poor noob asks about strange error messages that he had
stared at for last two hours? Me of course.

And you can tell him the issue in one minute.
Sure, it is harmful he sat
and stared there *and* it is harmful since more important things
had to wait while I solved such nonsense issue.

I don't know if a "C++ programmer" who has to sit and stare more than five
minutes to find out a namespace clash can produce many important things in
that time.
String may also (depending on problem domain) mean:
* a cord usually used to bind, fasten, or tie
* a plant fiber
* the gut, wire, or nylon cord of a musical instrument
* the action of lagging for break in billiards
etc. etc.

But in programming, a string is so universal and has a well defined
meaning, so you better don't use your exotic string unqualified.
So you techically say the applications for such domains should use names
like 'cord_used_to_tie' instead of 'string' and 'string' unqualified
instead of 'std::string'?

Use "yourdomain::string" for your exotic string class and just "string" for
std::string. And for the case that you are actually inside yourdomain
namespace, you can still use std::string qualified or if you don't use
std::string at all, just don't #include <string>.
I don't understand why now you are arguing with such convoluted names like
cord_used_to_tie. I never suggested not using namespaces at all.
Or ... if it is really a domain where string
means also 'line of characters' then why not to import string into
domain namespace with 'using std::string;' and so leave 'std::thread'
still unimported?

Why #including said:
Whole point of namespace std and namespaces in general seems to be is
apparently too dim for so lot of people.

The whole point of namespaces actually is, that you don't _have_ to use it
unless you have a name clash. And if you have one, you can fix it on the
client side.
Otherwise they would not be a real improvement over std_string and your
cord_used_to_tie.
First they use "using namespace"
a lot. Then they get clashes.

Then they used qualified names...
Then they fall back to age of in-name
qualifiers.

Huh, why that? Are they C programmers?
Result: the 30+ character names are not too uncommon and the code base
looks as an inelegant pile of bloat that it is.

You mean like: yourdomain::yoursubdomain::yoursubdubdomain::list?

Tobi
 
J

Jorgen Grahn

On 12/30/2012 10:55 PM, Jorgen Grahn wrote: (attribution lost)

I definitely would not pass on a review a homegrown class named 'list'.
Honestly can't even imagine an explanation why would one present it so.

Since my examples above were functions, would you object to them too?
How about 'Book find(const Library&)', for example?
Would you prefer find_book(), find_in_library(), ... ?

(Here I should point out that I don't know if my find() would be a
problematic name clash -- I never trade away the std:: in std::find.)

/Jorgen
 
B

Balog Pal

Since my examples above were functions, would you object to them too?

Functions are a different breed, as they form overload sets.
How about 'Book find(const Library&)', for example?
Would you prefer find_book(), find_in_library(), ... ?

Can't tell without context. The first rule of overload sets is that all
members have the same semantics. I mean SAME :).

A freestanding find()? I'd expect it to need two pieces of info: where
and what. And return an lvalue or some pointer/index/...

So I could possibly pass something like 'const Book& find(const Library&
where, BookID id)'. If some one part is implied, it will need a name
reflecting it. If it returns a copy of the located item, it should
reflect that too.
(Here I should point out that I don't know if my find() would be a
problematic name clash -- I never trade away the std:: in std::find.)

No, functions with the same name don't clash except for really special
cases -- they either hide or form an overload set, and work fine on
invocation. So majority of times they work fine without prefixes on
invocation. Sometimes you may hit ambiguity and need to help out for a
technical reason.

But the important thing is that just reading the code it shall suggest
what is happening really. The is the area name clashes hurt really,
not the technical ground. Reusing the same names for different purposes
usually just create confusion and bugs. You can dodge this problems if
the contexts are distinct. But std:: I consider as an omnipresent
thing, relevant in every context. If not used today, it can be picked up
tomorrow. So I suggest to avoid whatever names it uses -- except when
you aim to exactly match them.
 
B

Balog Pal

The prefix can be really informative on its own right. For example, suppose
you see this line of code:

if(equal(a, b, c))

what does that line tell to you? Not much, really. A function named
'equal', which might be defined *somewhere*, is being called with some
parameters. We can't really say where that function might be defined
(is it local to the current compilation unit, is it an extern function,
is it in some other library, is it a standard function...?) nor do we
know anything about those parameters.

But now, imagine that the line had been like this instead:

if(std::equal(a, b, c))

This is a whole lot more informative. Now we know *immediately* that it's
a call to a standard function, and we also know what the parameters are
(they are iterators or pointers). And even if you didn't know what
std::equal() does, at least you know where to look for that info.

A very good example, that should be framed on the wall.

Demonstrating the main misconception about code reading (and
consequently writing).

So, to answer your first question, the first line shout bell:

"that is a predicate function taking three items, not modifying them,
and returning true if all are equal". The second should bell the same +
"and it has noise".

The exact signature of the function, the place of its implementation,
and the other stuff is completely irrelevant. (If you actually need to
know it's an indication of systemic trouble.)

OTOH if you're in the marginal situation to need the implementation, it
is just a click or keystroke away, unless you use some stone-age tools.
 

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,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top