Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Newf
Feb 14, 2006
I appreciate hacky sack on a much deeper level than you.
Again, thanks. You can probably guess my level of competence in C++ - really I'm spending two thirds of my time just trying to make things compile.

Adbot
ADBOT LOVES YOU

qntm
Jun 17, 2009
I think you could be forgiven for your compiling issues given that apparently none of your error messages even have line numbers.

Newf
Feb 14, 2006
I appreciate hacky sack on a much deeper level than you.
Oh, they were there, I just removed them since they didn't correspond with the simplified snippets that I posted.

(woosh?)

Rottbott
Jul 27, 2006
DMC
Never use new. I can't think of any good reason someone new (aha) to C++ would need to use it unless they're using an ancient compiler for some reason, and probably not even then.

Newf
Feb 14, 2006
I appreciate hacky sack on a much deeper level than you.
Fine then, I won't.

Here's a more general (more stupid?) question about C(++). Why is it that when I look up something like ArrayList class from Java or .NET I'm brought to comprehensive documentation from the language specifiers (eg, Oracle and Microsoft) but when I look up std::vector I find sites like cplusplus.com?

Is there some hidden thing that I'm supposed to be using as a reference?

High Protein
Jul 12, 2009

Newf posted:

Fine then, I won't.

Here's a more general (more stupid?) question about C(++). Why is it that when I look up something like ArrayList class from Java or .NET I'm brought to comprehensive documentation from the language specifiers (eg, Oracle and Microsoft) but when I look up std::vector I find sites like cplusplus.com?

Is there some hidden thing that I'm supposed to be using as a reference?

Unfortunately that's the result of C++ not being owned by any one company, I think Visual Studio actually comes with STL docs too though.

As for 'new', afaik make_unique is C++14 so even with not-that-ancient compilers you'll have to use it.

Zopotantor
Feb 24, 2013

...und ist er drin dann lassen wir ihn niemals wieder raus...

Newf posted:

Here's a more general (more stupid?) question about C(++). Why is it that when I look up something like ArrayList class from Java or .NET I'm brought to comprehensive documentation from the language specifiers (eg, Oracle and Microsoft) but when I look up std::vector I find sites like cplusplus.com?

Is there some hidden thing that I'm supposed to be using as a reference?

C++ is not owned by a single company; the relevant reference would be the ISO C++ standard. It's not available online (though draft versions are) because it actually costs money. The latest drafts are available at the C++ Standards Committee website.

However, I wouldn't recommend using the standard for learning C++ - it's mostly an implementer's reference. Books like The C++ Programming Language are better for that.

Sites like the ones you already found are indeed your best bet for online searchable reference material - since it isn't a single-vendor language, there is no one authoritative C++ reference site.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

High Protein posted:

As for 'new', afaik make_unique is C++14 so even with not-that-ancient compilers you'll have to use it.
Defining it yourself for the non-array case is just template<typename T, typename... Args> T *make_unique(Args&&... args) { return new T(std::forward<Args>(args)...); }.

xgalaxy
Jan 27, 2004
i write code
http://en.cppreference.com/w/

The best site for C++ reference documentation.

Malcolm XML
Aug 8, 2009

I always knew it would end like this.

Plorkyeran posted:

Defining it yourself for the non-array case is just
code:
template<typename T, typename... Args> 
std::unique_ptr<T> make_unique(Args&&... args) 
{ 
     return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); 
}

Surely this is what you meant?

Could also add a static assert using is_array to guard against array types getting in there.

Deus Rex
Mar 5, 2005

xgalaxy posted:

http://en.cppreference.com/w/

The best site for C++ reference documentation.

If you have a Mac Dash gives you handy offline access to cppreference among like a hundred other documentation sets.

Star War Sex Parrot
Oct 2, 2003

Deus Rex posted:

If you have a Mac Dash gives you handy offline access to cppreference among like a hundred other documentation sets.
I was just thinking about a nicer way to access the cppreference stuff offline, and this is perfect!

Thanks.

qntm
Jun 17, 2009

Zopotantor posted:

C++ is not owned by a single company; the relevant reference would be the ISO C++ standard. It's not available online (though draft versions are) because it actually costs money. The latest drafts are available at the C++ Standards Committee website.

Why does the C++ specification cost money?

Jewel
May 2, 2009

Deus Rex posted:

If you have a Mac Dash gives you handy offline access to cppreference among like a hundred other documentation sets.

Woah, is there anything like this for Windows? This is a cool idea.

csammis
Aug 26, 2003

Mental Institution

qntm posted:

Why does the C++ specification cost money?

ISO is funded in part by the sale of the standards it curates.

http://wikipedia.org/wiki/International_Organization_for_Standardization

Sagacity
May 2, 2003
Hopefully my epitaph will be funnier than my custom title.

Jewel posted:

Woah, is there anything like this for Windows? This is a cool idea.
There's Zeal, but I haven't used it.

Jewel
May 2, 2009

Sagacity posted:

There's Zeal, but I haven't used it.

Yeah, I actually asked on twitter and the creator of Dash must have namesearched and replied to me with Zeal. I tried it out and it seems.. okay. It doesn't have method listings or anything like Dash does, and you can't search for stuff in only one language, it searches in all languages at once. Seems the bare minimum in usability really.

Sagacity
May 2, 2003
Hopefully my epitaph will be funnier than my custom title.
That's a shame. Maybe the simplest way is to just get a webscraper and download all your favorite docs? :)

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe
I was getting some advice today from a more senior developer at my work. I'm still new to this job (and to work as a coder in general), so for the time being they have had me reading over the details of an SDK they make available to companies interested in making use of one of their major products; this is with the twin aims of acquainting me with the company's stuff, and allowing me to suggest ways in which the docs might be improved as somebody using them from an outside perspective. So I've been making notes on the docs and making a toy application using the SDK. Anyway, I was asking this guy to look over my code and suggest anything that looked to him like it should be done differently. He's offered advice to me on that sort of thing before and I found it useful.

One thing he objected to was the use of code that looked something like this (I'm typing from memory, so if I get the name or signature of something wrong then that's why):

code:
try
{
    inputInt = std::strtoi(input);
    if (inputInt > maxAllowedValue)
    {
        throw std::out_of_range();
    }
}
catch (std::out_of_range)
{
    cout << "That number is too big!" << endl;
    return;
}
He felt that this use of try... catch was quite poor form (the term he used was that it was "an abuse of exceptions"). I asked him to explain further, and he explained that his expectation would be that a throw statement would not in general be so close in the source code (i.e. in the same function) to the catch block that catches its exception; nor would the throwing of an exception be used as a means to control program flow. He didn't particularly seem to like that an exception might be thrown in the course of "ordinary" program operation (i.e. in the case that a user of a command-line application enters bad input, which is something the application needs to be able to handle but is not "abnormal" in any way).

This is a bit alien to me, because my approach to exceptions is generally informed by how they are used in Python. I just wondered whether this is how things generally work in C++ land, or whether it's an idiosyncrasy of this place. At the end of the day, I won't be arguing with anyone, just doing as the company expects, but I was curious about this. The company has a set of standards that they apply to the code that they write - this guy has explained to me the reasons behind some of them, and in general I've been able to appreciate the rationale for everything, this one just seemed slightly strange.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
Using exceptions for mundane control flow is much more common in idiomatic Python than any other language I've used, but I'd wtf at code like that even in Python.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

Plorkyeran posted:

Using exceptions for mundane control flow is much more common in idiomatic Python than any other language I've used, but I'd wtf at code like that even in Python.

Could you elaborate on this? It is not very helpful to me, as a relative beginner, if you post comments along the lines of "that code is terrible" without explaining at least briefly why you think it is terrible.

astr0man
Feb 21, 2007

hollyeo deuroga
There is no reason to throw an exception there rather than just printing your error message and returning. The try/catch is just adding extra overhead that does absolutely nothing. It would make more sense if you just threw the exception, and then had whatever was calling your function catch it when it happens.

Vanadium
Jan 8, 2005

I'd expect to see exceptions used in situation where the code that notices the error doesn't know how to handle it, but some code way up in the callstack does, and exceptions are the best way to communicate the error upwards because throw immediately starts unwinding and jumps up the stack to the handler. In your example, you already know what you're gonna do about the error, so you might as well do it right away, and your throw surprisingly doesn't unwind anything or jump anywhere since the handler is basically in the next line anyway.

If strtoi threw that exception on its own and you were basically just unifying the handling of its error cases (number > INT_MAX or w/e) and your own error case (number > maxAllowedValue) in one exception handler, I could see writing it like this, but afaict strtoi doesn't throw any exceptions.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

astr0man posted:

There is no reason to throw an exception there rather than just printing your error message and returning. The try/catch is just adding extra overhead that does absolutely nothing. It would make more sense if you just threw the exception, and then had whatever was calling your function catch it when it happens.

I don't really follow why you say it would make more sense to just throw, and then have whatever was calling the function catch it. The function containing that code receives the string entered by the user and checks it for a variety of things (is it a valid menu selection? is it an indication that the user wants to go back to the previous menu? is it an indication that the user wants to quit the application? is it empty? is it a number, but outside of the range of numbers accepted? is it unintelligible gibberish?) and (hopefully) handles each one appropriately: by changing the state of the class, calling another method to do some requested action, or printing a helpful message saying what is wrong with the input. If all of the possible faults with the user's input were to result in an exception being sent to the caller, then the function would be leaving a large part of its job up to the caller. It would basically just move the response to the error condition elsewhere, when the idea was to have that stuff (which is more or less boilerplate that doesn't relate to the functionality of the application) consolidated in one place.

Given that I was using std::strtoi(), it isn't true that the try/catch does absolutely nothing. I would still need to catch std::out_of_range in case the user enters something like 999999999999999999999999999999999999999999999. Now of course you could argue that I might use something else instead of std::strtoi(), and indeed the guy I was talking to said that he would have chosen to use strtol(), but he didn't appear to feel that using std::strtoi() was wrong per se.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe
I remembered incorrectly; the function I was using is std::stoi(), not strtoi(). I apologise for the confusion, but I did note in my original post that I was typing from memory!

Star War Sex Parrot
Oct 2, 2003

Vanadium posted:

I'd expect to see exceptions used in situation where the code that notices the error doesn't know how to handle it, but some code way up in the callstack does, and exceptions are the best way to communicate the error upwards because throw immediately starts unwinding and jumps up the stack to the handler. In your example, you already know what you're gonna do about the error, so you might as well do it right away, and your throw surprisingly doesn't unwind anything or jump anywhere since the handler is basically in the next line anyway.
Basically this. What Hammerite did reminds me of how exceptions are taught in intro C++ classes, but don't actually demonstrate how and when they're actually used. It usually doesn't make a lot of sense to throw exceptions around in the same function, but instead they're used to communicate and even recover from a failure when unwinding the call stack.

Hammerite, what you did could easily just be handled without throwing an exception in the first place and instead just using normal control statements.

Volguus
Mar 3, 2009
You were using exception for control flow. Don't do that. It is a well known anti-pattern. Exceptions should be used for exceptional situations, not to break from a loop. Essentially, this usage is no better than a goto.

Here's a stackexchange thread that may be more helpful: http://programmers.stackexchange.com/questions/189222/are-exceptions-as-control-flow-considered-a-serious-antipattern-if-so-why

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
That you're using std::stoi is very relevant, and makes that code reasonable IMO specifically because you're reusing the error handling that you need anyway, unlike if it was std::strtol where the throw and catch would be pointlessly roundabout.

Volguus
Mar 3, 2009

Plorkyeran posted:

That you're using std::stoi is very relevant, and makes that code reasonable IMO specifically because you're reusing the error handling that you need anyway, unlike if it was std::strtol where the throw and catch would be pointlessly roundabout.

std:stoi throws std::out_of_range if the value falls out of the range of the type. Here maxAllowedValue is the business rule regarding that type. There are two very different things. Yes he needs that try/catch, but the catch is only for when the user enters a value that cannot be represented by an int. For when the user enters a reasonable int value, but that violates the business rules (maxAllowedValue) he should either throw his own exception so that somebody up the chain can handle that (show the user the error message for example) or just return like he does in his out_of_range catch.

Throwing an std::out_of_range because the user entered value 20 (if maxAllowedValue is 15 for example) is just control flow. It shouldn't be a habit to catch on.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

Plorkyeran posted:

That you're using std::stoi is very relevant, and makes that code reasonable IMO specifically because you're reusing the error handling that you need anyway, unlike if it was std::strtol where the throw and catch would be pointlessly roundabout.

An earlier version of the method did something like this:

code:
bool tooBig = false;
try
{
    inputInt = std::stoi(input); // not strtoi()!!!
}
catch (std::out_of_range)
{
    tooBig = true;
}
if (inputInt > maxAllowedValue)
{
    tooBig = true;
}
if (tooBig)
{
    cout << "That number is too big!" << endl;
    return;
}
until I looked at it and thought, "screw it, I can test both things in the same place and unify what happens when the number is too big". That's when I moved the test inside the try block and added the throw statement. It meant I could get rid of the boolean flag variable.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

Star War Sex Parrot posted:

Basically this. What Hammerite did reminds me of how exceptions are taught in intro C++ classes, but don't actually demonstrate how and when they're actually used. It usually doesn't make a lot of sense to throw exceptions around in the same function, but instead they're used to communicate and even recover from a failure when unwinding the call stack.

Hammerite, what you did could easily just be handled without throwing an exception in the first place and instead just using normal control statements.

I knew that they could. It's the should that caught me out.

raminasi
Jan 25, 2005

a last drink with no ice
I think Vexing exceptions is worth reading. And I'd like to reemphasize that Python's exception idioms don't exist in C++ (or any other mainstream language I've encountered).

e: I also think that you could defend what you did because stoi might throw that exception anyway, but that's the kind of thing that deserves a comment in the code.

Star War Sex Parrot
Oct 2, 2003

You also have to be careful with exceptions in C++ because if you're not adhering to RAII and throw an exception and don't remember to clean stuff up with the handler, you will leak memory.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

Star War Sex Parrot posted:

You also have to be careful in C++ because if you're not adhering to RAII you will leak memory.
ftfy

Writing exception-safe code in C++ is frequently easier than writing correct-but-unsafe code.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

rhag posted:

he should either throw his own exception so that somebody up the chain can handle that (show the user the error message for example) or just return like he does in his out_of_range catch.

Throwing an std::out_of_range because the user entered value 20 (if maxAllowedValue is 15 for example) is just control flow. It shouldn't be a habit to catch on.

So throwing std::out_of_range for a value above maxAllowedValue is control flow, but throwing mystuff::out_of_range isn't?

raminasi
Jan 25, 2005

a last drink with no ice

Plorkyeran posted:

So throwing std::out_of_range for a value above maxAllowedValue is control flow, but throwing mystuff::out_of_range isn't?

rhag is objecting to conflating a business rule with a library precondition. (I disagree that the difference matters here, but it is one.)

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

GrumpyDoctor posted:

rhag is objecting to conflating a business rule with a library precondition. (I disagree that the difference matters here, but it is one.)
I get that much, and I can buy the argument that using std::out_of_range for business logic violations is incorrect because it's for precondition violations, but I don't understand how throwing one type of exception is using exceptions for control flow but throwing another type isn't (or is acceptable control flow).

Volguus
Mar 3, 2009

Plorkyeran posted:

I get that much, and I can buy the argument that using std::out_of_range for business logic violations is incorrect because it's for precondition violations, but I don't understand how throwing one type of exception is using exceptions for control flow but throwing another type isn't (or is acceptable control flow).

Because you wouldn't (shoudlnt) catch your exception in the try/catch. That one is meant for whoever is calling you. In my opinion, the code would be better with something like this:

code:
try
{
    inputInt = std::strtoi(input);
    if (inputInt > maxAllowedValue)
    {
        throw invalid_input_exception("The value is not acceptable. Max acceptable value is "+std::to_string(maxAllowedValue));
    }
}
catch (std::out_of_range)
{
   throw invalid_input_exception("The value is not acceptable. Please enter a value between 0 and "+std::to_string(maxAllowedValue));
}
Then the caller can catch invalid_input_exception and do something (shouldn't show the message of an exception to the user, should be something more user friendly, but that's not relevant for this discussion), such as warn the user.
The cause of that exception is not really relevant to the caller, so it shouldn't be burdened with that.

Why is this better than just throwing std::out_of_range? Because tomorrow you may change the code, to convert a string to int using some other algorithm. One that doesn't throw std::out_of_range. Or maybe you will do some other black magic inside your function. By only telling your caller that the only thing he has to worry about is invalid_output_exception, you are now free to do whatever you want in your function, use whatever algorithm you want and just make sure that you throw that exception if you dont like the input (for whatever reason). A change in the business rules should only be your problem, not the caller's.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

rhag posted:

Why is this better than just throwing std::out_of_range? Because tomorrow you may change the code, to convert a string to int using some other algorithm. One that doesn't throw std::out_of_range. Or maybe you will do some other black magic inside your function. By only telling your caller that the only thing he has to worry about is invalid_output_exception, you are now free to do whatever you want in your function, use whatever algorithm you want and just make sure that you throw that exception if you dont like the input (for whatever reason). A change in the business rules should only be your problem, not the caller's.
The fact that some std::out_of_range are coming directly from your function and some happen to be bubbling out is an implementation detail that the caller does not need to be aware of. If you need to change to a different string parsing method that signals errors in a different way, then you just have to throw std::out_of_range whenever the new string parsing method signals that the value is out of range. Choosing an interface which simplifies your implementation does not mean that your interface has to change to keep your implementation simple, and in this case your implementation after changing would be identical to what it would have been if you prematurely pessimized by translating std::out_of_range (other than the name of the exception being thrown, obviously).

Adbot
ADBOT LOVES YOU

Volguus
Mar 3, 2009

Plorkyeran posted:

The fact that some std::out_of_range are coming directly from your function and some happen to be bubbling out is an implementation detail that the caller does not need to be aware of. If you need to change to a different string parsing method that signals errors in a different way, then you just have to throw std::out_of_range whenever the new string parsing method signals that the value is out of range. Choosing an interface which simplifies your implementation does not mean that your interface has to change to keep your implementation simple, and in this case your implementation after changing would be identical to what it would have been if you prematurely pessimized by translating std::out_of_range (other than the name of the exception being thrown, obviously).

But if the business rules change so that the input is invalid for some other reason (mars, earth and the sun are in alignment for example) then throwing out_of_range is kinda ... wrong, isn't it? The input is invalid. Why? Why do you care? It's invalid and that's that.

The input doesn't have to be "out of range" to be invalid, that's my entire point. Hiding that implementation detail from the caller is, in my opinion, good design practice.
Then again, probably in most real world cases this may not matter, no matter what you throw out (if anything, just returning may be just fine). Of course, in cases where good design practices have a performance penalty ... then screw good design. But usually, it pays in the long run.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply