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
tractor fanatic
Sep 9, 2005

Pillbug

GrumpyDoctor posted:

3. cout name is invalid C++ syntax. Any time you see word otherword (that I can think of) you've done something wrong. That snippet should be cout << name.

identifier otheridentifier is visually wrong but keyword identifier happens all the time. If you're new and you don't have syntax highlighting or your editor highlights cout it's not immediately visible that something is wrong.

Adbot
ADBOT LOVES YOU

raminasi
Jan 25, 2005

a last drink with no ice

hooah posted:

Thanks for your helpful reply. 3 and 4 I really should have caught myself. I removed the accessor for the struct and removed the scope operator in the member function.

Now my question is how do I access the public data members? Specifically, in the cout statement, how do I access an element in a vector within the struct?

I just noticed another problem: if (*it.get_name(name) == name) should be if ((*it).get_name(name) == name), which is so common that it has its own shorthand operator: if (it->get_name(name) == name). This is also broken, because get_name isn't const, but the_grades is and so it is a const_iterator, but since you've eliminated get_name you won't have a problem. (Another alternative would have been to make get_name const.)

You access object fields the same way you do object methods: cout << it->my_name << " " << it->values[0] would print the name and the first grade, for example.

tractor fanatic posted:

identifier otheridentifier is visually wrong but keyword identifier happens all the time. If you're new and you don't have syntax highlighting or your editor highlights cout it's not immediately visible that something is wrong.

Whoops, yeah!

Rottbott
Jul 27, 2006
DMC

GrumpyDoctor posted:

8. grades student_1 = grades("Ben"); can be written grades student_1("Ben");.

In this case grades student_1 = "Ben"; would also work because the constructor isn't marked explicit. However, it should be explicit.

hooah
Feb 6, 2006
WTF?

GrumpyDoctor posted:

I just noticed another problem: if (*it.get_name(name) == name) should be if ((*it).get_name(name) == name), which is so common that it has its own shorthand operator: if (it->get_name(name) == name). This is also broken, because get_name isn't const, but the_grades is and so it is a const_iterator, but since you've eliminated get_name you won't have a problem. (Another alternative would have been to make get_name const.)

I'd noticed this and fixed it myself, but good to see that I'm not entirely out of my mind.

quote:

You access object fields the same way you do object methods: cout << it->my_name << " " << it->values[0] would print the name and the first grade, for example.

And this does it! Thanks! Now I just have to figure out how to apply what I've learned with this small example to my previous project.

Rottbott posted:

In this case grades student_1 = "Ben"; would also work because the constructor isn't marked explicit. However, it should be explicit.

What does it mean for a constructor to be marked explicit? What's the difference between the two types of initializations, grades student_1 = "Ben"; and grades student_1("Ben");?

hooah fucked around with this message at 18:38 on Sep 23, 2013

raminasi
Jan 25, 2005

a last drink with no ice

hooah posted:

I'd noticed this and fixed it myself, but good to see that I'm not entirely out of my mind.


And this does it! Thanks!


What does it mean for a constructor to be marked explicit? What's the difference between the two types of initializations, grades student_1 = "Ben"; and grades student_1("Ben");?

If a constructor has a single argument of a different type, it has the effect of creating the possibility of implicit conversion from the argument type to the constructed type. It's why things like std::string butts = "butts" work even though the literal "butts" isn't an std::string. That this happens automatically is widely regarded as dumb because, for example, in your case, there's no real reason to want implicit conversion from std::strings to gradebook entries (or specifically, from const char *s to std::strings to gradebook entries), but you can opt out of it by placing the explicit keyword before the constructor definition, and so it's considered best practice to always use the explicit keyword for single-argument constructors unless you're intentionally trying to enable implicit conversion (which requires a good reason for doing so).

On any modern compiler there isn't going to be a practical difference (other than readability) between the two different forms of initialization unless you're getting bitten by unintended implicit conversion. Here, of course, readability would be an actual issue, because grades student_1 = "Ben" doesn't really make any sense.

b0lt
Apr 29, 2005

hooah posted:

What does it mean for a constructor to be marked explicit? What's the difference between the two types of initializations, grades student_1 = "Ben"; and grades student_1("Ben");?

Constructors that have one argument that aren't tagged explicit can be used for implicit conversion in C++, which leads to really dumb and annoying poo poo happening in most cases. See here for an example.

hooah
Feb 6, 2006
WTF?
Now I want to be able to find a specific student's list of grades without making the user supply the name of the gradebook (since there really will only ever be one). I'd like to modify the findname function I wrote and remove the second parameter. In my attempt, however, I see that I'm not sure how to refer to the book of grades that has been created. Here is the relevant part of my header file:
code:
	struct book_entry
	{
		string my_name;
		vector<double> grades;

		book_entry(string name)
		{
			my_name = name;
			vector<double> grades;
		}

		void get_student(string &name) {
				for (auto it = my_book.begin(); it != my_book.end(); ++it) {
					if ((*it).my_name == name) {
						cout << name << " " << it->values[0];
					}
				}
		}

		void add_grade(int number) {
			grades.push_back(number);
		}
	};

private:
	string my_student_name;
	string my_assignment;
	vector<book_entry> my_book;
	double my_grade;
I've tried setting it to point at the beginning of my_book, which is a vector of structs, but that gives me an error that "a nonstatic member reference must be relative to a specific object", which doesn't mean much to me. What am I missing?

nielsm
Jun 1, 2009



The core problem is that you are putting the "find some member of the gradebook" function inside the struct that defined a specific member.
Move the get_student function out of the book_entry struct into the gradebook class. Finding a student by name in the gradebook isn't an operation on a student, it's an operation on the gradebook.

Syntactically, book_entry.get_student("Ben") is also problematic because book_entry is a type name, and you can't access members of types (because they are not instances.) If get_student had been a static member function you could have used the :: scope resolution syntax to call it, but that still wouldn't make logical sense, for the reason above.

When you make get_student a member function of the gradebook class then it gets access to the private members of the class which is the reason you get compilation errors inside the function.


Have you perhaps worked in Java before?

hooah
Feb 6, 2006
WTF?

nielsm posted:

Syntactically, book_entry.get_student("Ben") is also problematic because book_entry is a type name, and you can't access members of types (because they are not instances.) If get_student had been a static member function you could have used the :: scope resolution syntax to call it, but that still wouldn't make logical sense, for the reason above.

This helped, thanks.

quote:

Have you perhaps worked in Java before?

Not besides a few lessons on Code Academy. Perhaps surprisingly, I've already taken a class in C++ (although it was a short summer semester class at a community college).

OzyMandrill
Aug 12, 2013

Look upon my words
and despair

It may help if you get your head around how classes & member functions actually work in terms of passing the current object around:

code:
 class myClass {
   void my_function(int,int);
 };

 myClass c;
 c.my_function(a,b)
is effectively* handled by the compiler as:

code:
Definition:
     _myClass_my_function( myClass *this, a, b )
     {
         ...
     }
Use:
  _myClass_my_function(c, a, b);
so a member function has a hidden 'this' field as the first parameter. Syntactically, whatever object you use the '.' or ''->' operator on will be inserted as this first parameter & so becomes available inside the member function as 'this'

If you don't have an instance of 'c', then you obviously don't have a 'c' to pass.
Instead, you make a static function:
code:
 class myClass {
   static void my_function(int,int);
 };

 myClass::my_function(a,b);
which just makes the internal function:
code:
 void _myClass_my_function(int,int);
There are C++ precompilers that can convert C++ to plain C by doing this conversion (and vtables become static member arrays of function pointers), and someone once told me that C++ was originally designed to be converted to plain C before dedicated C++ compilers were written.




Now to the specific example, to get the page of the book:
code:
class Book
{
  struct book_entry
  {
  };

  vector<book_entry> my_book;
  book_entry GetStudent(string &name); // This searches the vector for the correct book_entry
};

book_entry Book::GetStudent(string &name)
{
 ...
and now in this function you can refer to 'this.my_book' where the 'this.' can be left out - it is implied simply by being inside a member function.

*the actual names generated in the compiler will also contain a scary combinations of letters & stuff denoting argument types which is generally how type overloading is resolved, but they are compiler specific.

Bonfire Lit
Jul 9, 2008

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

OzyMandrill posted:

someone once told me that C++ was originally designed to be converted to plain C before dedicated C++ compilers were written.
Cfront

Boz0r
Sep 7, 2006
The Rocketship in action.
I'm trying to do a 2D array of a dynamic size so I'm using vectors. I'm doing a bucket sort on a bunch of nodes with a value, throwing all of these in buckets with the same value. My problem is, that the second dimension of vectors are null so I get an exception when i try to add to that bucket. I need a way to test if the vector is null and then initialize it, or whatever.

code:
// Add nodes to buckets
	for (int i = 0; i < nodes.size(); i++) {
		std::shared_ptr<FNode> currentNode = nodes.at(i);		
		bucketList.at(currentNode->rank).push_back(currentNode);
	}
This crashes if bucketList.at(rank) is null.

raminasi
Jan 25, 2005

a last drink with no ice
Can you provide a little more context? It's kind of hard to figure out what you're doing.

Boz0r
Sep 7, 2006
The Rocketship in action.
I'll try to explain it better when I get home, but basically, I have a vector of vectors. I need a way to check if the second level of vector exists before I can add anything to it, or else it crashes.

Just as if I was doing arrays like [x][y], and I always had to check if array y exists for each x.

nielsm
Jun 1, 2009



Is that a vector of (smart-)pointers to vectors, or a vector of actual vectors?

The first case:
C++ code:
vectpr< shared_ptr< vector< thing > > > bucketList;
The second case:
C++ code:
vector< vector< thing > > bucketList;
In both cases, you'd start by checking that the index even exists (i >= 0 && i < bucketList.size()) and if it doesn't then resize the outer vector.

In the second case (straight vector of vectors) you'd then be done.

In the first case you'd then have to pull out the smart pointer, check that it's valid, if not then initialise it with a new vector object as appropriate, and then operate on it.

Deep Dish Fuckfest
Sep 6, 2006

Advanced
Computer Touching


Toilet Rascal
Quick question: I've been reading through "The C++ Programming Language: 4th Edition" mainly to get a good idea of new C++11 features, but I've just encountered something I thought wasn't actually allowed in C++. At the end of Section 20.5, it's mentioned that

quote:

A compiler may reorder sections of a class with different access specifiers. For example:
C++ code:
class S {
public:
	int m1;
public:
	int m2;
};
The compiler may decide for m2 to precede m1 in the layout of an S object.

Now, I know about padding and alignment issues, and I wouldn't expect the object's memory layout to just be every member packed as tight as possible. But I was 100% certain that compilers weren't allowed to reorder members, period. The wording in the book is pretty explicit, so I really doubt that this is a case of me misunderstanding something, so let me ask: has any compiler actually ever done this in practice? Is there any point, other than maybe eliminating some padding if you're lucky?

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
Huh. I was also under the impression that wasn't allowed, but the spec is pretty loving explicit:

C++11 §9.2.14 posted:

Nonstatic data members of a (non-union) class with the same access control (Clause 11) are allocated so that later members have higher addresses within a class object. The order of allocation of non-static data members with different access control is unspecified (11). Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other; so might requirements for space for managing virtual functions (10.3) and virtual base classes (10.1).
The spec even appears to allow interleaving the various sections...

OddObserver
Apr 3, 2009
I wonder why they didn't just make "only public POD data" (aka compatible with a C struct) a special case?

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
A C struct would only have public members, so no need for a special case.

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!
Why even do that? Doing it for public members makes sense for C compatibility, but the rest is a weird half-way to member reordering.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
The committee is full of people with really bad ideas about how to make a programming language. It's gotten better recently, but it's been pretty appalling for most of its existence.

The "different access control specifiers" thing is an attempt to allow reordering even of public fields as long as the struct has obvious C++ features, probably because they want to make sure that things like std::pair are subject to it. It's even somewhat suggestive, because the thing that breaks the guarantee also visually breaks apart the fields, see!

The real answer is that field reordering should be universally allowed outside of the narrow case of structs for which C layout compatibility is guaranteed. (This used to be what "POD" meant, but the term got borrowed by other parts of the spec, then later generalized to suit their purposes, basically for no good reason.) The use cases for comparing field addresses are completely negligible. Use a nested C-compatible struct if it's really that important.

Rottbott
Jul 27, 2006
DMC
It is somewhat annoying to be obliged to order my fields manually for best alignment/size instead of putting them in a logical order and letting the compiler do that. Sometimes you need exact control but usually not.

Jewel
May 2, 2009

Rottbott posted:

It is somewhat annoying to be obliged to order my fields manually for best alignment/size instead of putting them in a logical order and letting the compiler do that. Sometimes you need exact control but usually not.

That's the thing. Usually not. Why do you have to manually tell it to pack rather than manually tell it to stay unpacked. Seems a weird decision.

OzyMandrill
Aug 12, 2013

Look upon my words
and despair

Is there (will there be) a standard way to tell the compiler NOT to reorder things?
Or will there end up being a mess of compiler specific pragmas or whatever for backwards compatibility?

Most of the projects I have worked on rely on strict member ordering so we can load game data & just fix up pointers, by far the fastest & most controlled way to load MBs of data quickly... (Not to mention the current lack of definition about where the vtable pointer actually goes, that at least has a workaround)

If this starts happening, I can see a lot of very annoyed programmers wondering why their files have stopped loading...

Boz0r
Sep 7, 2006
The Rocketship in action.

nielsm posted:

Is that a vector of (smart-)pointers to vectors, or a vector of actual vectors?

The first case:
C++ code:
vectpr< shared_ptr< vector< thing > > > bucketList;
The second case:
C++ code:
vector< vector< thing > > bucketList;
In both cases, you'd start by checking that the index even exists (i >= 0 && i < bucketList.size()) and if it doesn't then resize the outer vector.

In the second case (straight vector of vectors) you'd then be done.

In the first case you'd then have to pull out the smart pointer, check that it's valid, if not then initialise it with a new vector object as appropriate, and then operate on it.

Thanks. I don't know why I didn't think of this, it's obvious in retrospect.

tractor fanatic
Sep 9, 2005

Pillbug

Is that a typo or are both m1 and m2 public?

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

OzyMandrill posted:

Is there (will there be) a standard way to tell the compiler NOT to reorder things?
Or will there end up being a mess of compiler specific pragmas or whatever for backwards compatibility?

If you want a portable guarantee here, just put all your fields under the same access control specifier. If you're willing to go with "it just works", then you have nothing to worry about, because nobody does field reordering as far as I'm aware of.

I have a hard time believing that your memory dump save scheme won't inevitably bite you in the rear end, though.

Ciaphas
Nov 20, 2005

> BEWARE, COWARD :ovr:


fritz posted:

Do people still willingly use sun cc?

Depends on if you define "willingly" as "because I like my job otherwise".

kill me

astr0man
Feb 21, 2007

hollyeo deuroga

Ciaphas posted:

Depends on if you define "willingly" as "because I like my job otherwise".

kill me

We use it too.

:smith::hf::smith:

csammis
Aug 26, 2003

Mental Institution

astr0man posted:

We use it too.

:smith::hf::smith:

Joining this club :toot:

At least our R&D department is taking part in the Sun Studio 13 beta which should put our compiler stack able to consume C++11 in approximately 2015

Slash
Apr 7, 2011

Ciaphas posted:

Depends on if you define "willingly" as "because I like my job otherwise".

kill me

Yep we use it too, although we're currently in the process of moving off of Solaris and onto Linux, so hopefully not for much longer.

Deep Dish Fuckfest
Sep 6, 2006

Advanced
Computer Touching


Toilet Rascal

tractor fanatic posted:

Is that a typo or are both m1 and m2 public?

No, it's not a typo.

Anyhow, thanks for the info about how this whole "reordering access specifier blocks" behavior came about. At least now if I ever see someone putting "private:" in front of every single data member in a class definition, I'll know they're probably not crazy. Just pedantic, showing off, or a combination of the two. Or a Java/C# programmer forced to do C++ at gunpoint, I guess.

Rottbott
Jul 27, 2006
DMC

YeOldeButchere posted:

Or a Java/C# programmer forced to do C++ at gunpoint, I guess.
Almost certainly this one. I never put more than one of each, and I always put them in the order public, protected, private. That way people reading the header see the parts they're actually interested in first, and don't have to go hunting through the whole file to check if there are any other public parts sneakily hidden in amongst other crap. I hate that.

an skeleton
Apr 23, 2012

scowls @ u
I'm making a simple C++ program which quizzes you on the spelling of greek letters. problem is, I don't think greek letters are part of ASCII and so I'm not sure how to display them in the console. Any bright ideas?

nielsm
Jun 1, 2009



an skeleton posted:

I'm making a simple C++ program which quizzes you on the spelling of greek letters. problem is, I don't think greek letters are part of ASCII and so I'm not sure how to display them in the console. Any bright ideas?

Unicode

Boz0r
Sep 7, 2006
The Rocketship in action.
My friend submitted the following code:

code:
std::unordered_map<int, std::shared_ptr<BNode>> map;

...

map.insert({{k,node}});
He writes in Linux and I use Visual Studio 2012. VS won't compile the insert call. Is this a correct method call, and if so, why doesn't it compile in VS?

Falcorum
Oct 21, 2010

Boz0r posted:

My friend submitted the following code:

code:
std::unordered_map<int, std::shared_ptr<BNode>> map;

...

map.insert({{k,node}});
He writes in Linux and I use Visual Studio 2012. VS won't compile the insert call. Is this a correct method call, and if so, why doesn't it compile in VS?

It's valid syntax, but it uses initializer lists and uniform initialization (both are part of C++11) and VS2012 doesn't support either of those.

Boz0r
Sep 7, 2006
The Rocketship in action.
Damnit, Microsoft, I thought VS2012 supported all of C++11. What about VS2013? I think I can get that through uni.

EDIT: Or, how should I write it in VS2012?

Boz0r fucked around with this message at 12:34 on Sep 29, 2013

hooah
Feb 6, 2006
WTF?

Boz0r posted:

Damnit, Microsoft, I thought VS2012 supported all of C++11. What about VS2013? I think I can get that through uni.

EDIT: Or, how should I write it in VS2012?

2013 does support (at least most of) C++11. There's a list somewhere on the VS website that says what C++11 standards are supported in which versions.

Adbot
ADBOT LOVES YOU

Rottbott
Jul 27, 2006
DMC

Boz0r posted:

Damnit, Microsoft, I thought VS2012 supported all of C++11. What about VS2013? I think I can get that through uni.

EDIT: Or, how should I write it in VS2012?

Like this, I think:
code:
map.insert(std::make_pair(k, node));

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