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
DrSunshine
Mar 23, 2009

Did I just say that out loud~~?!!!

Tetraptous posted:

If you're using C++11, std::any_of does exactly what you want.

Nice!! Thanks!

Adbot
ADBOT LOVES YOU

VikingofRock
Aug 24, 2008




DrSunshine posted:

I want to compare some variable against a set of numbers inside of a vector that the user can specify. For example:

code:
	myVector = <1, 3, 4>
	if (x == any of the values inside myVector){
		do something
	}
How would I go about doing this? I'm kind of blanking on this, but I'm fairly certain it involves std::find somehow.

In case you were interested in doing this with std::find, this works:

C++ code:
#include <iostream>
#include <algorithm>
#include <vector>

int main() {
    std::vector<int> v {1,2,3,4,5};
    int x = 3;
    if(std::find(v.begin(), v.end(), x) != v.end()){
    	std::cout << "Found it!" << std::endl;
    }
}

//outputs "Found it!"

DrSunshine
Mar 23, 2009

Did I just say that out loud~~?!!!

VikingofRock posted:

In case you were interested in doing this with std::find, this works:

C++ code:
#include <iostream>
#include <algorithm>
#include <vector>

int main() {
    std::vector<int> v {1,2,3,4,5};
    int x = 3;
    if(std::find(v.begin(), v.end(), x) != v.end()){
    	std::cout << "Found it!" << std::endl;
    }
}

//outputs "Found it!"

Huh, neat! I think this makes more sense to me syntaxwise, but there's something I'm curious about. In "std::find(v.begin(), v.end(), x) != v.end()", why does it work with != v.end()? Like, what is it telling the computer to do, exactly? I know that != means not equal to, but I'm kind of confused as to what it translates to in this context.

DrSunshine fucked around with this message at 14:41 on Jul 22, 2015

nielsm
Jun 1, 2009



In C++ STL, container::end() returns an iterator that represents "one past the last element", i.o.w. an iterator for an element that doesn't exist. If std::find() returns an end iterator, it indicates that no elements were found.

DrSunshine
Mar 23, 2009

Did I just say that out loud~~?!!!

nielsm posted:

In C++ STL, container::end() returns an iterator that represents "one past the last element", i.o.w. an iterator for an element that doesn't exist. If std::find() returns an end iterator, it indicates that no elements were found.

Ah I see! Thanks a lot! That helps clarify things immensely.

So, what if instead of finding at least one of the items in the vector, I wanted it to exclude all of the items in it. So rather than ∃x(x ϵ v) it was ¬Ɐx(x ϵ v), how would I do that? Would I use std::all_of ?

nielsm
Jun 1, 2009



You mean you have a vector A with elements, and another vector B with elements, and you want to produce a vector C that contains all elements that are in A but not in B?

I think there is a remove_if function you can use, but not sure. Or consider using the std::set type instead, it has a simpler interface for set-like operations.

Doc Block
Apr 15, 2003
Fun Shoe
I have a kinda weird question: why do so many C++ developers make their for loops use prefix increment instead of postfix increment? In other words, why do they use ++i instead of i++? Like,
C++ code:
for(auto i = 0; i < whatever; ++i)
instead of the more "normal"
C++ code:
for(auto i = 0; i < whatever; i++)
?

I'm an Objective-C programmer, and I almost never see prefix increment in Objective-C or C code, and I don't recall it being used terribly often when I first started using C++ back in the early 2000s, but now that I'm trying to re-learn C++ I see it quite often in online C++11 examples and such.

Zopotantor
Feb 24, 2013

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

Doc Block posted:

I have a kinda weird question: why do so many C++ developers make their for loops use prefix increment instead of postfix increment?
For me, it's because the first C compiler I ever used was so lovely that it actually created worse code for postfix increment even with an integer index. (Alcyon C on the Atari ST :corsair:)

In C++, the postfix operator has to create a temporary value while the prefix operator can just return a reference to *this. Modern compilers should optimize the temporary away when it is not used, but some of us still don't trust them...

nielsm
Jun 1, 2009



Zopotantor posted:

For me, it's because the first C compiler I ever used was so lovely that it actually created worse code for postfix increment even with an integer index. (Alcyon C on the Atari ST :corsair:)

In C++, the postfix operator has to create a temporary value while the prefix operator can just return a reference to *this. Modern compilers should optimize the temporary away when it is not used, but some of us still don't trust them...

More importantly it can cause problems with some non-trivial iterators that need to copy themselves. That's the main risk. In the end it's always a question of micro-performance.

Doc Block
Apr 15, 2003
Fun Shoe
I see, thanks. Having to get used to a language where class instances can be created on the stack and iterators are separate objects is kinda weird after so many years of writing Objective-C.

Does the C++ compiler have to create temporary variables even for integer indexes? Like, when compiled without optimizations, is there still a difference between
C++ code:
int limit = whatever
for(int i = 0; i < limit; i++)
and
C++ code:
int limit = whatever
for(int i = 0; i < limit; ++i)
?

edit: With integer indexes, clang seems to generate the same code for prefix and postfix. Gonna be different for iterators though, thanks for the info.

Doc Block fucked around with this message at 18:14 on Jul 22, 2015

nielsm
Jun 1, 2009



Strictly, i++ must be turned into a sequence of "store old value in a temporary, increment variable, use temporary as result", even when the result is unused. A dumb compiler could then end up generating instructions and storage for the temporary in all cases. A simple compiler might special-case for integers where the result is obviously unused, perhaps even only in for loops. A modern, optimizing compiler would detect most cases and avoid the temporary.

However if your compiler+linker toolchain doesn't have whole-program optimization, avoiding the temporary in non-inlined overloaded postfix operators gets tricky.
Consider a program in three files:
C++ code:
// terrible.h
struct terrible {
  int value;
  terrible operator++(int);
};

// terrible.cpp
#include "terrible.h"
terrible terrible::operator++(int) {
  terrible temp = *this;
  value += 1;
  return temp;
}

// program.cpp
#include "terrible.h"

int main() {
  terrible x;
  for (x.value = 0; x.value < 10; x++) {
    // ...
  }
}
If you build the two cpp files to separate objects and link them to a program, the compiler and linker both have no way of knowing what sort of side effects the postfix increment operator might have. Therefore it has to generate the copy and function call etc. involved in using the operator.

To avoid that, the compiler would either have to generate two different versions of the overloaded operator, with different names, for the cases of result used or result unused, and then call the appropriate one at the site. This makes for a strange ABI, and special-cases postfix ++ and -- operators, not very neat. Otherwise it would have to do whole-program optimization with some sort of link-time code generation.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Doc Block posted:

Does the C++ compiler have to create temporary variables even for integer indexes? Like, when compiled without optimizations, is there still a difference between
C++ code:
int limit = whatever
for(int i = 0; i < limit; i++)
and
C++ code:
int limit = whatever
for(int i = 0; i < limit; ++i)
?

No. In a modern compiler, the frontend will generally break this down into individual load, add, and store operations, and the difference between the operators is just whether it chooses the result of the load or the result of the add as the result of the expression. In this code, the result is unused, and so the IR should end up looking exactly the same to the backend code emitter. There are more complex l-values (notably, bitfields) that can require additional work to prepare the result, but even then, in code like this the frontend can tell immediately that the result is unused and therefore avoid doing that work.

Whether the unoptimized code emitter is clever enough to select an in-memory increment instruction for that sequence (when available) is a separate question. For Clang on x86, the answer is no; we emit separate load, add, and store instructions. In contrast, GCC probably would use that instruction because IIRC they don't have a special, dumber code emitter for unoptimized code.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
The main reason the class case is different is that those are user-defined operators, and there is absolutely no language guarantee that the user-defined postfix and prefix increment operators do semantically-related operations, or even that they both exist and are usable. The compiler is required to call the one you used, end of story.

nielsm is correct that, in principle, you could hack the ABI so that the compiler emitted different variants of a function depending on whether the result was unused. Specifically, for return values with non-trivial destructors, this would only be usable when the next thing the caller would do is destroy the return value; you would not be able to use this for the first operator call in a++, b++, because the destructor for the temporary cannot be called until the end of the entire expression. And, in that variant, you would still have to do the copy-construction and destruction of the result; it's just that the compiler might be able to eliminate them with the as-if rule.

Doc Block
Apr 15, 2003
Fun Shoe
Just another argument against operator overloading, heh :haw: :clint:

LtSmash
Dec 18, 2005

Will we next create false gods to rule over us? How proud we have become, and how blind.

-Sister Miriam Godwinson,
"We Must Dissent"

Could someone help me figure out how this macro works?
code:
#define REV32(x)            ((#@x & 0x000000FFU) << 24 | (#@x & 0x0000FF00U) << 8 | (#@x & 0x00FF0000U) >> 8 | (#@x & 0xFF000000U) >> 24)
Its used like so:
code:
case REV32(CNAM):
Always with 4 characters. It works and I understand the result is reversed bytes, but I don't understand what #@ does in there.

Subjunctive
Sep 12, 2006

✨sparkle and shine✨

I have never seen #@ before in my life. Do you have a weird compiler or preprocessor in play?

(Or maybe this is some C++25 thing.)

sarehu
Apr 20, 2007

(call/cc call/cc)
#x would expand to "CNAM", it looks like #@x is supposed to expand to 'CNAM', which is a multi-byte character constant.

Edit: Behold! https://msdn.microsoft.com/en-us/library/91tt6dfs.aspx

sarehu fucked around with this message at 01:56 on Jul 27, 2015

LtSmash
Dec 18, 2005

Will we next create false gods to rule over us? How proud we have become, and how blind.

-Sister Miriam Godwinson,
"We Must Dissent"

Subjunctive posted:

I have never seen #@ before in my life. Do you have a weird compiler or preprocessor in play?

(Or maybe this is some C++25 thing.)

Neither had anyone else I asked but through dumb persistence I managed to find its a visual studio specific preprocessor feature: the charizing operator that turns the parameter into a character the same way # turns the parameter into a string. It apparently also works to turn the parameter into a non null terminated character array if its more than character long.

efb but I didn't reload for ages.

yippee cahier
Mar 28, 2005

nevermind, thought it was a uint32_t byte swapper

Xarn
Jun 26, 2015
I am not entirely sure this falls under scope of this thread, but this seems like the best place to ask anyway.

I have a chance to significantly alter the C/C++ course taught at my university. Its current state is the usual C89+C++98 basics that needlessly repeat things from prerequisite courses and then end before saying anything useful about templates. Obviously I would prefer to burn things to the ground and start anew, but that is not an option (yet :ssh:) so I am going to try and get C dropped, because there isn't enough time to do modern C AND C++ (hell, there isn't enough time to do C++ properly, but that is another story and another fight) and everything currently in the course is covered by direct prerequisite. I am also going to push to update C++ part to C++11 with C++14 elements (basically taking the current MSVC as the least common denominator).

So now I am looking for ideas (You HAVE to teach r-value references), opinions (You are dumb for dropping C) and examples of high quality C++ courses (Stroustrup's PPP using C++ seems pretty good) to use as references for the changes.

nielsm
Jun 1, 2009



Is that course a general "introduction to programming" course, or is it intended for students who already know other languages to learn C and/or C++?

Xarn
Jun 26, 2015

nielsm posted:

Is that course a general "introduction to programming" course, or is it intended for students who already know other languages to learn C and/or C++?

No, the "introduction to programming" is the (two semester) prerequisite. However the current state feels a lot like it is.

Blotto Skorzany
Nov 7, 2008

He's a PSoC, loose and runnin'
came the whisper from each lip
And he's here to do some business with
the bad ADC on his chip
bad ADC on his chiiiiip
What is the title of that C-and-C++ course, and what is its ultimate purpose?

Star War Sex Parrot
Oct 2, 2003

Neat, it sounds like you have an opportunity to change the C++ course to be more like the one I tutor for at my university. It's called "C++ as a Second Language" and is taught after students already have a year of programming experience. The course is meant for CS-type majors, and isn't the type of programming class that like engineers would take to satisfy their "one class of programming" requirements.

It's expected that they already know about basic data types, flow of control statements like ifs and loops, writing classes, and working with libraries (albeit all with Python). In theory that allows the C++ course to get right to the specifics of its own language. I'll see if I can dig up a typical list of topics and class schedule for the course. We're on quarters, so in 10 weeks we tend to go through some STL usage, RAII (assignments frequently must use dynamic memory allocation and are not allowed to leak memory), exceptions, inheritance and polymorphism, lambdas, templates, smart pointers, and writing unit tests with Google Test. There might be more I'm forgetting, but those seem to be the big ones to me. The quarter system still limits the depth of material, but when taught this way, I think you have a really effective foundation for a good Data Structures course taught with C++.

Edit: here's a schedule and topic list from last year, if it helps. The first two weeks are spent sort of introducing students to the language based on where they've come from. There are also some code examples on the site as well if you want to see how some of the topics are demonstrated.

Star War Sex Parrot fucked around with this message at 20:54 on Jul 28, 2015

crazypenguin
Mar 9, 2005
nothing witty here, move along

Blotto Skorzany posted:

What is the title of that C-and-C++ course, and what is its ultimate purpose?

Pretty much this. Every course design should start with learning objectives.

Talking about the specific things they should learn about C/C++ is just a (bad) proxy for talking about what they should be prepared for after taking the course. Go examine what courses list it as a prerequisite, and talk to those instructors about what they need students to know from the course. Then design from there.

Xarn
Jun 26, 2015

Blotto Skorzany posted:

What is the title of that C-and-C++ course, and what is its ultimate purpose?

The title is "Programming in C/C++" and the purpose is to teach someone who supposedly has at least basic understanding of programming in some other language some C++. Ideally it would give large degree of competency, but without getting more time, the target is usable competency. The closest to proper requirement on the course is that the computer vision guys would really like course that teaches their students to take Matlab prototype and make something roughly demoable.

Its not a formal prerequisite for any other course, and it isn't informal prerequisite for any courses either. Some courses want their student to understand C, but there is already a course to help catch up with C in low level environment. The only course to take an informal dependency in the near future is going to be advanced C++ and that is only if someone pushes is through. (It is currently blocked by academic elitism and politics)

Sex Bumbo
Aug 14, 2004
The ability to reason about memory and how/where it gets allocated is one of the biggest reasons I like C++, so that's what I would want to learn about. Stl stuff like move or forward are pretty important to memory management and somewhat unique to C++. Things like lambdas or vectors or inheritence is not, those are snoozers that should be talked about in a data structures class or something.

sarehu
Apr 20, 2007

(call/cc call/cc)
Using standard containers like vectors and making abstractions with templates is a very important part of C++.

nielsm
Jun 1, 2009



Basic stuff, but cover the ideas behind RAII and what promises it carries for alternate return paths and exceptions. Make sure to contrast it with goto-cleanup patterns in C error handling. (That's also the place to put in a criticism of Dijkstra's famous essay, why it has served its purpose and is no longer relevant.)

Also the logical concept of object ownership (who is responsible for creating and destroying things), which students who come from garbage collected languages might not be used to thinking about, and how it relates to std::unique_ptr and std::shared_ptr, and why shared pointers can be risky.

If the students have had a data structures class as a prerequisite, cover how the STL container classes and algorithms map to the various commonly known structures. Since C++ is a close-to-the-metal language, also consider covering why algorithmic complexity isn't always the best measure for speed - why std::vector may be faster than std::list in almost every case.

Sex Bumbo
Aug 14, 2004
Explaining how vectors work isn't useful because they're in like every language already and the implementations aren't particularly different. But stuff like emplacing into a vector or moving it around is language specific. The STL algorithms library shouldn't be something that needs to be taught imo but it's also grotesque so it probably does.

Subjunctive
Sep 12, 2006

✨sparkle and shine✨

Explaining vector<bool> is a good way to engender the right level of suspicion.

Sex Bumbo
Aug 14, 2004
At the risk of sounding ignorant why does it even still exist?

sarehu
Apr 20, 2007

(call/cc call/cc)

Sex Bumbo posted:

Explaining how vectors work isn't useful because they're in like every language already and the implementations aren't particularly different. But stuff like emplacing into a vector or moving it around is language specific. The STL algorithms library shouldn't be something that needs to be taught imo but it's also grotesque so it probably does.

What I'm saying is you shouldn't teach C++ with just.. pointers and no STL containers as the things you use.

But come to think of it you should ideally, given infinite time, teach how vectors are implemented, like the way Accelerated C++ does. It's not the same as in other languages, since you have to construct objects in-place and such.

Sex Bumbo
Aug 14, 2004
Yeah, I just have a lot of not-fond-memories of expensive "advanced" classes that had 4 weeks of redundant baloney from, often times, another class that I was taking at the exact same time. e.g. data structures (which was in C++) vs "advanced" C++, and for half a semester it was like taking the same class twice. We covered more data structures in the C++ class for a while too.

nielsm
Jun 1, 2009



Sex Bumbo posted:

Explaining how vectors work isn't useful because they're in like every language already and the implementations aren't particularly different. But stuff like emplacing into a vector or moving it around is language specific. The STL algorithms library shouldn't be something that needs to be taught imo but it's also grotesque so it probably does.

My suggestion is also not to explain what a vector/dynamic array is, but rather assume the students know their basic algorithms and data structures, and just explain how the STL maps to those.

Like, from the name alone it isn't really clear that std::map is usually implemented with a balanced tree.

Bonfire Lit
Jul 9, 2008

If you're one of the sinners who caused this please unfriend me now.

Sex Bumbo posted:

At the risk of sounding ignorant why does it even still exist?
same reason trigraphs were in the standard up to C++14: someone somewhere (IBM) depends on it

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
Making vector<bool> a normal container at this point would be a pretty painful breaking change for anything actually using it heavily, since the code using it would still compile and pass functional tests, but would suddenly start using 8 times as much memory and be way slower.

There's a few people pushing to take advantage of the backwards-compatiblity break when the standard library is Conceptified to clean up all the old cruft and bad decisions, but I suspect that'll get bogged down in endless committees.

raminasi
Jan 25, 2005

a last drink with no ice

Plorkyeran posted:

There's a few people pushing to take advantage of the backwards-compatiblity break when the standard library is Conceptified to clean up all the old cruft and bad decisions, but I suspect that'll get bogged down in endless committees.

To be fair, a lot of things are going to be different once the heat death of the universe rolls around.

b0lt
Apr 29, 2005

Plorkyeran posted:

Making vector<bool> a normal container at this point would be a pretty painful breaking change for anything actually using it heavily, since the code using it would still compile and pass functional tests, but would suddenly start using 8 times as much memory and be way slower.

There's a few people pushing to take advantage of the backwards-compatiblity break when the standard library is Conceptified to clean up all the old cruft and bad decisions, but I suspect that'll get bogged down in endless committees.

It wouldn't necessarily be way slower, depending on access patterns.

Adbot
ADBOT LOVES YOU

Xarn
Jun 26, 2015

Plorkyeran posted:

There's a few people pushing to take advantage of the backwards-compatiblity break when the standard library is Conceptified to clean up all the old cruft and bad decisions, but I suspect that'll get bogged down in endless committees.

My money is on minor cleanups being done and then a fuckton of bikeshedding blocking anything interesting.

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