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
Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
I'm currently reading Beginning C++ through Game Programming and am almost done, so I wanted to ask here what would be a logical next step? I should mention I prefer books, simply because I find them easier to read and they're generally more mobile.

I might decide to write a couple of text based applications before I move on to further cement the stuff I've learnt from the book, but I'd like to have a new book lying around for when I feel ready to move on.

I was thinking I'd move on with a book on a GUI or Windows API, or maybe APIs in general, or is that too advanced? If it is too advanced, are there any books that cover that middle-ground?

It should be mentioned that I have no prior experience with programming before starting to read this book.

Thanks.

EDIT: Fixed the book title.

Joda fucked around with this message at 14:26 on Apr 8, 2011

Adbot
ADBOT LOVES YOU

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe

nielsm posted:

Write a load of programs. Maybe learn a simple library for doing fancier-than-iostreams text interfaces, something like Ncurses if you can find a version that works for you.

While doing that, learn a second language. I'd recommend Python, it's similar enough that you can transfer some knowledge and not start entirely blank, but different enough that you'll be forced to think and re-organise what you've learned so far, making you a better programmer overall.

Then begin thinking about real GUI.

Can't help with books.

Thanks. I did a quick search on Amazon and found this, which I might pick up when I feel secure enough in C++.

In the meantime; are there any libraries that come with the standard libraries of either g++ or MS Visual Studio 2010, that allow a beginner such as myself to do basic stuff such as clear the console before reprinting output, maybe add colour or something like that to the text and write/read from separate files on the hard-drive? I don't expect there to be any books on something that narrow and outdated, but I'd settle for an online tutorial just to get a grip of the objects and functions.

Joda fucked around with this message at 16:20 on Apr 8, 2011

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
Great! Thanks for the help.

I tried looking at the link you posted nielsm, but it all seems pretty daunting to me, and ANSI escape codes seem a lot simpler. I do most coding on my laptop which has Ubuntu and g++, so Windows incompatibility shouldn't pose a major problem.

Just to make sure I understood it right; this should end up as a blank console, right?

code:
#include <iostream>

int main()
{
  std::cout << "Something!\[2J";

  return 0;
}
That's what I could gather from cross checking that table with a quick google search at least, but I might not've understood it right.

EDIT: Corrected code and understood why it's a good idea to get more used to the language before moving on :downs:

Joda fucked around with this message at 20:30 on Apr 8, 2011

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
Yeah, I read that I can define them as char variables so in practice I'll probably define a global const char variable like this:

const char CLEAR = '\033[2J';

and use it like this:

cout << "Something!" << CLEAR;

and just use that to avoid confusing myself with concepts I haven't even learnt about yet (i.e. #define) so I at least have some faint idea what I'm doing.

Thanks a lot for your help :)

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe

Mustach posted:

I recommend that beginners read The Practice of Programming. It's a well-written book that covers several fundamental subjects. It also contains many exercises and projects that are more interesting than printing colored text.

The part about coloured text (and more importantly, clearing the console) was more about also doing some practice on UI design while further familiarising myself with C++. Knowing how to do that wasn't by any means an ends by themselves, but more a way for me to have some kind of tools, no matter how basic, to experiment with making my applications easier to understand and use.

Like I already said I'm almost done with an introductory book, and I'd say it's done a pretty good job of making me understand the concepts and syntax of C++ at a basic level, and before moving on I'll try and make some applications on my own.

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
My head doesn't work right. Nvm this post.

EDIT: I realised that while I was reading through my post. I changed the conditional to use iterGene1 and it works like it should now. My head has the worst timing. Thanks though. vvvvvv

Joda fucked around with this message at 18:21 on Apr 20, 2011

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
I'm trying to set up Netbeans 8.0 for C++, and have so far been able to make it work pretty well. Everything compiles like you'd expect. However, I have an issue with it not wanting to recognise member functions of the vector [class. I have the vector declared and initialised but when I type out the following line of code:

C++ code:
currentState = stateList.begin();
where currentstate is an iterator and stateList is a vector, I get an error on the begin() saying Netbeans is unable to resolve it as an identifier. Furthermore, when I remove the begin(), to see autocomplete options, it only shows vector constructors. The code compiles as expected, so I'm fairly sure it's a problem with Netbeans.

Is there an easy way to fix this?

E: If it's relevant, the standard I use is C++11, I use g++-4.8 to compile and code assistance has links to the relevant directories for g++-4.8.

E2: Apparently it works if I revert to gcc to version 4.6. Then I can't use C++11, though.

Joda fucked around with this message at 22:12 on Mar 19, 2014

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
I'm having an issue with a vector of int vectors suddenly having an obscene size after trying to pass it through a couple of classes.

Here is the vector I'm creating in main, and how I pass it on to the class that needs it:

C++ code:
    std::vector< std::vector<int> > rules = std::vector< std::vector<int> >();
    std::vector<int> rule = {0,0,0,10000,0};
    
    rules.push_back(rule);
    
    std::cout << "Ruleset size in main(): " << rules.size() << std::endl;
    
    sm.addState(rules,move);
    sm.update(1,false);
Here is addState in StateMachine (which sm is an instance of)

C++ code:
void StateMachine::addState(std::vector< std::vector<int> > ruleSet, Move stateMove)
{
  std::cout << "Ruleset size in StateMachine::addState(): " << ruleSet.size() << std::endl;
    
  State newState(ruleSet, stateNumber, stateMove);
  stateList.push_back(&newState);
}
Here is the State constructor

C++ code:
State::State(std::vector< std::vector<int> > ruleSet, int& sMachineState, Move stateMove) {
  this->currentMachineState = sMachineState;
  this->ruleSet = ruleSet;
  startTime = (int) std::time(0);
  this->stateMove = stateMove;
  
  std::cout << "Ruleset size for Class in State constructor: " << this->ruleSet.size() << std::endl;
}
And finally here is the State update function (which is called from the StateMachine update function):

C++ code:
void State::update(int input, bool isJumping)
{
  std::cout << "Ruleset size in state::update(): " << ruleSet.size() << std::endl;
    
  int elapsedTime = (int) std::time(0) - startTime;
  
  for(auto iter = ruleSet.begin(); iter != ruleSet.end(); iter++) {
    
    if(input == iter->at(0) &&
      (int) isJumping == iter->at(1) &&
      elapsedTime > iter->at(2) &&
      elapsedTime < iter->at(3))
    {
        currentMachineState = iter->at(4);
    }
  }
}
Notice how I added debug statements to keep an eye on the size of my ruleset as it's passed down. This is the ouput I get:

code:
Ruleset size in main(): 1
Ruleset size in StateMachine::addState(): 1
Ruleset size for Class in State constructor: 1
Ruleset size in state::update(): 6148908827317490774

RUN FINISHED; Segmentation fault; real time: 0ms; user: 0ms; system: 0ms
Obviously I get a segmentation fault because it thinks my ruleset is much larger than it really is. As far as I can tell, the original ruleset from main is assigned properly in the State constructor, but for some reason when I access it in the update() function it suddenly has an absolutely obscene size (a size which varies greatly from run to run.)

Does anyone know how such an issue can occur and what steps I can take to debug it?

Joda fucked around with this message at 05:17 on Mar 21, 2014

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
Oh, thanks. Is there any way to call the constructor in that function or do I have to pass a pointer to a State as an argument?

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
I'm getting a weird error when trying to initialise a class as a member of another class. I have a Character class with a member Rect bounding, but for some reason when I call the Rect constructor in the Character constructor it, for some reason, thinks I'm not giving it any arguments. I made a dummy class to see if I could recreate the issue, and it seems to be a general problem with Rect.

This is my Dummy class:
C++ code:
class Dummy {
public:
    Dummy();
    Rect bounding;
};

Dummy::Dummy() {
    this->bounding = Rect(100,100,Math::iVec2(100,100));
}
The Rect class declaration:

C++ code:
class Rect : public Shape {
public:
    Rect(int width, int height, Math::iVec2 position);
    
    bool intersect(Rect* rectangle);
    bool contains(Math::iVec2 point);
    
    void draw();
    void update();
    
    Math::iVec2 getVertex(int index);
    
private:
    Math::iVec2 vertices[4];
    int width;
    int height;
    
    void updateVertices();
};
and the Rect constructor:
C++ code:
Rect::Rect(int width, int height, Math::iVec2 position) {
    this->width = width;
    this->height = height;
    this->position = position;
    updateVertices();
}
This is the error I get:
code:
Dummy.h:19:14: error: no matching function for call to ‘Rect::Rect()’
 Dummy::Dummy() {
              ^
Dummy.h:19:14: note: candidates are:
In file included from Dummy.h:11:0,
                 from main.cpp:6:
Shape.h:38:5: note: Rect::Rect(int, int, Math::iVec2)
     Rect(int width, int height, Math::iVec2 position);
     ^
Shape.h:38:5: note:   candidate expects 3 arguments, 0 provided
I have no clue as to why it seems to ignore that I am, in fact, giving the constructor three arguments.

If I make bounding into a pointer to a Rect and allocate it on the heap with new, the class compiles and runs as expected, but I'd rather avoid allocating on the heap, since I'm working on an embedded system and every bit of optimisation helps.

This is the Dummy class that works btw:
C++ code:
class Dummy {
public:
    Dummy();
    Rect* bounding;
};

Dummy::Dummy() {
    this->bounding = new Rect(100,100,Math::iVec2(100,100));
}
E: I should note that this problem is exclusive to Rect. Any other class works fine as a member of another class. The only place I'm able to make an instance of Rect is main() and I can call members and member functions from there.

Joda fucked around with this message at 14:34 on Apr 7, 2014

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
code:
Dummy.h:19:18: error: type ‘Rect’ is not a direct base of ‘Dummy’
 Dummy::Dummy() : Rect(100 ,100, Math::iVec2(100,100)) {
This is the error I get if I use that line of code. Rect isn't supposed to be a superclass to Dummy.
I also tried adding an empty default constructor for Rect and now my code compiles fine. However, when I make a call for bounding from main() I get the following error:

code:
main.cpp:13:24: error: request for member ‘bounding’ in ‘dummy’, which is of non-class type ‘Dummy()’
     std::cout << dummy.bounding.getVertex(0).x << std::endl;
this is my main():
C++ code:
Dummy dummy();

std::cout << dummy.bounding.getVertex(0).x << std::endl;
I'm not sure if it's saying bounding is of non-class type Dummy or dummy is. I feel like I made a fairly obvious mistake somewhere. Also, I have another class where I'm able to initialise all members and fields in the constructor without issue. I thought the point of a constructor was that you could use it to initialise members?

I'm coming from Java, so I'm sure I picked up loads of bad habbits which are giving me hell now.

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
Sweet! That fixed it. Thanks for the help.

I'm still a bit confused as to why I can initialise an iVec2 in a constructor and not a Rect, but at least now I know how to handle that error.

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
I guess I didn't explain this, but iVec2 has a specified constructor as well, and no default constructor.

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
Does C++ have garbage collection akin to that of Java? I know you have to explicitly delete items on the heap, but if an item on the stack no longer has any references to it (like if something is referred to exclusively by a pointer, and I set that pointer to nullptr,) does the space automatically get freed up, or is there something I need to do? As far as I've been able to pick up, delete can only be used for items allocated on the heap.

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
I'm trying to make a linked list for the embedded project I'm working on (because STL isn't readily available,) and I'm trying to rewrite it so it uses the stack rather than the heap. How would you go about instantiating a linked list object for the next pointer without using the heap?

what I have now:
C++ code:
template <class T>
void push_back(T elementToAdd)
{
	LinkedList<T>* temp = this;

	while(temp->next != nullptr)
		temp = temp->next;

	temp->next = new LinkedList(T(elementToAdd));
}
The way I want to do it, the only reference to the new element in the list would be a next pointer, but with the element on the stack in stead of the heap. Based on what you say, I can't figure out how to do that without the element getting destroyed.

E: I should note that C++11 won't necessarily be an option.

Joda fucked around with this message at 01:46 on May 7, 2014

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe

Heavy neutrino posted:

Hey guys, I'm a non-computer person who recently decided to become one, and being hopelessly hard-headed I chose C++ as a starting point via Beginning C++ Through Game Programming, which I've just finished.

I started on this book way back, but forgot everything once I started uni where everything had to be Java (I'm now kicking myself in the head for not hanging on to it.) One thing I do remember it not covering, though, is make files, headers and conventions for how these are used (unless he changed it in a newer edition.) If you want to start doing projects around 500 lines or more, I'd definitely recommend reading up on that specifically, because debugging/expanding a 500 lines main file with all your classes is making things unnecessarily hard on yourself.

E: Is he still recommending DevCpp? If so, you should get yourself acquainted with a modern IDE (I like NetBeans, but its code assistance does suffer from it being originally made for Java) and learn how to set up a toolchain in it. Most IDEs will set up a default toolchain too, and will generate make files and such for you. Some are also able to analyse your code real-time, auto-complete your function calls/declarations, point out if you're referencing a non-existent member or member function, possible memory leaks, etc.

Joda fucked around with this message at 13:56 on May 14, 2014

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
You seem to be mixing pseudo-code with actual C++ code there, so it's kind of hard to go through and look for issues, since I'm not sure what parts are supposed to be in working order. Assuming your "if (player = 1)" isn't a typo/pseudo-code you should look up the difference between the assignment operator (=) and the "equal to" comparison operator (==).

As it is now the game will always enter the first of the if-statements.

Joda fucked around with this message at 10:55 on Sep 11, 2014

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe

The Gay Bean posted:

Would it be worth my time to read into a book and try to understand what compilers are actually doing, and if so, which book would be good to start with? Sorry if these are stupid questions, but I don't have a formal CS education (engineering).

Depending on your depth of understanding of hardware and compilers, Elements of Computing Systems might be worth a read as an introductory book. It goes from creating logic gates, to creating hardware implementations, creating your own assembly to use with this hardware, assembler, compiler, etc. Mind, if you're busy you might find it a tad too time consuming. It doesn't directly give you any concrete implementations, but makes you create everything from the ground up yourself (using a framework provided with the book) after it explains the basic theory of what you're about to implement.

Also, like I said it's an introductory book, meant to give a very basic understanding of Von Neumann architecture and its implementation. It doesn't cover things like busses, external hardware, concurrent concepts, etc.

E: If you're an electrical engineer you probably already did most of the logic gates and hardware implementation, but the framework that comes with the book has hard-coded implementations of everything previous to the current step so you can start anywhere you want.

E2: Just remembered that some university has hosted the book, exercises and framework here. If you do think it's something for you, though, I'd highly recommend getting the actual book. I found it really nice to have as a reference while I was coding.

Joda fucked around with this message at 16:41 on Dec 1, 2014

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
Been trying out CLion and in its unfinished state it is already much better than qtcreator (The inconsistent auto completion was getting on my nerves.) Only problem I have is that I'm doing a lot of graphics programming with OpenGL lately and the lack of GLSL support makes me sad.

Also, my laptop has a dual GPU setup, so I need to run GL applications through optirun, and I can't figure out how to tell it to run "optirun [executable]" since all custom arguments are put at the end of the command. Does anyone know how to do this?

Joda fucked around with this message at 04:34 on Dec 22, 2014

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe

xgalaxy posted:

QTCreator is an abomination and I don't know why anyone recommends it. CLion is great if you like having a cross platform IDE with great refactoring support for C++. However it is a huge disappointment in the debugging department because it just uses GDB -- which I don't know why I expected different. If I need to debug something nothing beats Visual Studio.

It's the only IDE I've found for Linux that has somewhat decent GLSL highlighting and code completion.

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
I have a Cmake/linking question. I set up a project to use GLM, GLFW and SOIL, and while GLFW and GLM come with Cmake files and are compiled with my project, which I assume means the relevant parts of the library are compiled into my executable and it will work when I try to run it on a system that doesn't have these libraries installed. SOIL, however, doesn't come with a Cmake file, and I have to link the library file and include files through my CmakeList. If I took my application and ran it on a system that doesn't have libSOIL.a in the particular path I do, would it then still work? These are the lines where I'm defining/linking SOIL in my CMakeList.txt:

code:
#Find SOIL
set( SOIL_INCLUDE_DIR "${PROJECT_DIR}/soil/src/")
set( SOIL_LIBRARIES "${PROJECT_DIR}/soil/lib/libSOIL.a" )
#Link SOIL
target_link_libraries(glfwtest SOIL ${SOIL_LIBRARIES})
I've never had to set up a major project for a stand-alone application that uses libraries before so I'm still not sure how all this works.

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
First of all none of those are errors, they're all warnings. As you can see your build succeeded, I am not sure if the code itself works, but here's what I noticed:

It seems like you're passing pointers to arrays in stead of pointers to the first element. If it works like C++ (If I understand the relationship between C and C++ correctly it should) the most common method is to send a pointer to the first element of the array and include the size if you want it to support variable sizes, like this:

C code:
void foo(int* bar, int size) {
	for(int i = 0; i < size, i++) {
		printf("%d\n", bar[i]); //[i] operator adds size of int*i and dereferences
	}
}

int main() {
	int bar[3] = {1,2,3};
	foo(&(bar[0]),3); //& operator returns pointer to element
	
	return 0;
}

This should print 1 2 3 in separate lines to the console.

Your first warnings:

code:
1>c:\users\amir\documents\visual studio 2010\projects\struct2\struct2\appears.c(19): warning C4047: 'function' : 'appear **' differs in levels of indirection from 'appear [26]'
1>c:\users\amir\documents\visual studio 2010\projects\struct2\struct2\appears.c(19): warning C4024: 'initAppearStruct' : different types for formal and actual parameter 1
Happen because you try to send the array in stead of a pointer to an element of type appear, which is what the compiler expects based on your function definition. You need to change the call from initAppearStruct(appStruct); to initAppearStruct(&(appStruct[0]));, so that the compiler understands exactly what you want to do (which is to send a pointer to the first element. (E: On second thought this is wrong; the problem here is also with forward declaration and definition disparity; you send a single pointer, but based on the forward declaration it expects a double pointer or a pointer to an array.)

The next warning:

code:
1>c:\users\amir\documents\visual studio 2010\projects\struct2\struct2\appears.c(25): warning C4028: formal parameter 1 different from declaration
Happens because your function forward declaration (line 12) calls for different parameters (pointer to an array, in stead of an element of type appear). You need to fix your forward declaration of the same function to fit what you put in the actual definition in line 24.

The final one is because you're comparing i, a signed integer, with the length of a string, an unsigned integer. It shouldn't matter since i is only ever incremented and never reaches values high enough to overflow.

E: The method of sending a pointer to the first element is how I always do it but if I remember correctly the compiler will also understand it if you just send the array directly, since an array handle is just the pointer to the first element. Your biggest issue is with the forward declaration of initAppearStruct, and the inconsistency of types.

Joda fucked around with this message at 00:35 on Feb 23, 2015

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
The majority of C/C++ frameworks my school provides for classes are like that, so that's what I'm most used to seeing. But yeah, in terms of functionality it shouldn't matter which you use, which is why I edited my post, and I agree foo(array) is a lot more readable.

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
Crossposting from the Game Dev thread, since this is probably more of a C++ issue.

I have a problem with compiling GLFW with my project in Windows with MinGW. The issue seems to be that when compiling GLFW it tries to do so with X11 headers, which, naturally, aren't available on Windows. I assume there's some flag or system variable I haven't set somewhere that I'm supposed to, but I can't figure out what the problem is. This is the error message I get (I get multiple, but they all refer to the same missing header):

code:
mingw32-make.exe[3]: *** [glfw/src/CMakeFiles/glfw.dir/gamma.c.obj] Error 1
In file included from C:\Users\NAME\ClionProjects\clion\glfwtest\glfw\src\internal.h:73:0,
                 from C:\Users\NAME\ClionProjects\clion\glfwtest\glfw\src\init.c:28:
C:\Users\NAME\ClionProjects\clion\glfwtest\glfw\src\x11_platform.h:34:22: fatal error: X11/Xlib.h: No such file or directory
 #include <X11/Xlib.h>
                      ^
And this is my own CMakeList: http://pastebin.com/FcX51R3U

Everything compiles fine under Unix.

Does anyone know what's going on here?

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
Thanks, using a fresh download of GLFW did the trick. I'd done a simple git pull of what I'd used on my Linux machine, and I guess the GLFW cmakelist didn't know to reconfigure, so I added it to my ignore list.

Of course, now SOIL is acting up for some reason. Same cmakelist as before, but for some reason it won't link the libSOIL.a because it can't recognise -lSOIL.

code:
c:/mingw/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe: cannot find -lSOIL
collect2.exe: error: ld returned 1 exit status
I fixed it by globing all cpp and c files in the SOIL src directory and compiling them with my main file, but I can't help but feel this is a hack that I will probably regret before long.

E: And of course GLM gives issues as well. Who knew cross-compatibility was such a pain.

Joda fucked around with this message at 04:33 on Mar 9, 2015

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe

PRADA SLUT posted:

code:
    Student aStudent("a", 3.1);
    Student *pStudent = new Student("b", 2.5);
To my understanding, the first line is the default constructor for student, then a new Student is created as a pointer back to the memory location of aStudent, just with different vars?

Those are two different ways to initialise an object of type Student, and are, as far as I can tell, only meant to illustrate that. They have no inherent relationship. The first allocates a Student on the stack (In simple terms, the part of your memory pool that has a fixed size,) while the other allocates a Student on the heap (the part of your memory that is dynamically allocated) and gives you a pointer to that object. They both use the same constructor, the only difference is where they are in memory and how you treat them when you call member functions and such. A constructor is, again in simple terms, a function that you can call to initialise an object with the values you want, and you need to write this constructor yourself like you would any other function, and set the values you want in there. I.e. you define it like you would any other member function except it doesn't have a return value. When you've done this you can call it to initialise a new Student object.

For instance:

C++ code:
class foo {
	foo(int a, int b);
	int a; 
	int b;
};
//The compiler doesn't automatically know what to initialise a and b to; we have to explicitly tell it.
foo::foo(int a, int b) {
	this->a = a; //the argument a "hides" the member a, so we have to use this->
	this->b = b;
	//All members have now been intialised.
}

PRADA SLUT posted:

When I need to call the function for comparison and output (returns true/false), do I just call bool Student::isLessThanByGpa(const Student& aStudent); in main?

When you want to call a member function you just write objectIdentifier.memberFunction(arguments). If it has return value you can assign it to something with the = operator (i.e. bool returned = objectIdentifier.memberFunction(arguments)). So, for instance, if you wanted to compare the two students from the earlier quote by GPA you would write something like

bool aLessThanB = aStudent.isLessThanByGpa(*(pStudent));

I don't know if you're familiar with pointers, but since pStudent is a pointer in the former example it is necessary here to dereference. If pStudent had been allocated on the stack it would be

bool aLessThanB = aStudent.isLessThanByGpa(pStudent);

E: Come to think of it I've never had to dereference something like that (i.e. *(pStudent)) so I'm not sure if it'd work.

Joda fucked around with this message at 07:17 on Mar 14, 2015

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
Yeah I actually fixed that. & returns a pointer * should dereference. Those two operators always gently caress me over.

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
Something not related: I'm pretty sure if you do 5/9*f.getTemperature() you'll really be getting 5/(9*f.getTemperature()), which is entirely different from (5/9)*f.getTemperature() because of order of operations. Also, in that fraction you need to make one of them floating point (i.e. 5.0f/9) or it will evaluate as an int division and become 0.

In general, always use floats in your constants if you're doing a floating point operation, and if you're unsure about order of operations, make ample use of parentheses.

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
Does std::atomic work like I think it does? I'm not particularly good at deciphering tech talk, so the C++ reference page doesn't really tell me much, and in the Concurrent Programming course I took we only worked with Java Monitors (as much as I dislike working with Java, this is one thing I love about it.) Based on the name, my assumption is that if I have an std::atomic<int> i = 0 and have 100 separate threads do i++, it will always end up with a value of 100 (whereas with a regular int it could be anything between 1 and 100.) Is this assumption correct?

E: Also related, do C++ threads work like Java tasks? As far as I can tell no matter if I pass it a function that increments a global atomic_int or a regular int, they both come out correct. When we did the same experiment in class, non-monitored functions would produce wildly varying results.

E2: Am I wrong in thinking that incrementation/addition is not an inherently atomic action?

Joda fucked around with this message at 16:44 on Apr 22, 2015

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
Thanks for the answer. I reconfigured my test so that it does three actions over a loop with 1000 iterations, and am still scratching my head at the result. I defined an invariant that value x (for non-atomic) and value y (for atomic) should be 0 for an arbitrary number of threads, and expected both of them to give garbage-looking results without any modifications (since I'm doing 3 atomic actions per iteration, assuming atomic operations.) However, only the function using atomic values actually produces garbage. This is the code:
C++ code:
std::atomic_int l(0);
std::atomic_int k(0);
std::atomic_int y(0);

int m = 0;
int n = 0;
int x = 0;

void f() {
    for(int i = 0; i < 1000; i++) {
        k++;
        l++;
        y += k - l;
    }
}

void f2() {
    for(int i = 0; i < 1000; i++) {
        m++;
        n++;
        x += m - n;
    }
}

int main() {

    std::vector<std::thread> threads = std::vector<std::thread>();

    for(int i = 0; i < ITERATIONS; i++) {
        threads.push_back(std::thread(f2));//.detach();
        threads.push_back(std::thread(f));//.detach();
    }

    for(int i = 0; i < ITERATIONS*2; i++) {
        threads[i].join();
    }

    std::cout << "Without atomic: " << x << std::endl;
    std::cout << "With atomic: " << y << std::endl;

    return 0;
}
For 10000 threads it produces the following results:

code:
Without atomic: 0
With atomic: 1123
The with atomic result is expected, as mentioned, but I have no clue why the without atomic result consistently produces the expected values. I implemented a semaphore, and modified the function using atomics to use that to protect the critical region:

C++ code:
class Semaphore {
public:
    Semaphore();
    void V();
    void P();
private:
    std::atomic_int tokens;
};

Semaphore::Semaphore() :
tokens(1)
{
}

void Semaphore::P() {
    while(tokens.load(std::memory_order_acquire) <= 0) {
        tokens.store(0,std::memory_order_release);
        std::this_thread::sleep_for (std::chrono::milliseconds(1));
    }
    tokens.fetch_sub(1,std::memory_order_release);
}

void Semaphore::V() {
    tokens.fetch_add(1,std::memory_order_acq_rel);
}
C++ code:
Semaphore* sem = new Semaphore();

void f() {
    sem->P();
    for(int i = 0; i < 1000; i++) {
        k++;
        l++;
        y += k - l;
    }
    sem->V();
}
I don't think the semaphore works entirely as I intended, since it sometimes produces wrong results, but the majority of the time I now get this:

code:
Without atomic: 0
With atomic: 0
What baffles me the most is that I always get the right result with f2, but any feedback on this test and what I may have misunderstood would be greatly appreciated.

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe

Jabor posted:

Atomic variables don't magically solve concurrency problems, which appears to be what you're expecting them to do. Specifically, nothing in your atomic example guarantees that one thread will complete an entire iteration of the loop before some other thread touches one of the variables.

Not at all. Like I said I expected the initial result for f(). Unless what you're saying is that memory orders don't work like I think they do, and my semaphore implementation is incorrect? What I expect the semaphore-version of the f() to do is ensure that only one thread can access the loop at any one time.

E: My thinking is that when I acquire a resource, no other thread can access it until the thread that acquired it has released it. Is this thinking incorrect?

E2: I realize my semaphore doesn't really work, because its results are inconsistent, but I'm not sure how to protect my critical regions if I can't lock down a resource.

Joda fucked around with this message at 10:03 on Apr 23, 2015

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe

Sex Bumbo posted:

Effort post

This is great, thanks! Also provides some motivation to actually give a poo poo about cache level optimisations.

I definitely see the fake synchronisation offered by sleeping the threads, without sleeps, wrong results get even worse.

Jabor posted:

Sorry, I just went to the code and skimmed the text. Your understanding of the original atomic stuff seems fine.

Your semaphore implementation, though, seems wonky. You should take a closer look at your P() implementation, and think on what happens if your thread is interrupted (and another thread does something with the semaphore) immediately after you do the load in the loop condition.

Do you mean the possibility of a deadlock? I hadn't considered that, so it's definitely going on my to-do, but right now I just want to be able to synchronize threads that I know won't be interrupted.

I tried changing the semaphore to use a mutex, since that is apparently the standard for protecting critical regions, but I'm still getting garbage results. I'm sure I'm missing something obvious, since I tried just using a global mutex to protect the loop itself in f(), and I still get wrong results:

Semaphore:
C++ code:
class Semaphore {
public:
    Semaphore();
    void V();
    void P();
    int getTokens();
private:
    std::atomic_int tokens;
    std::mutex mut;
};

Semaphore::Semaphore() :
        tokens(1)
{
}

void Semaphore::P() {
    mut.lock();
    while(tokens <= 0) {
        mut.unlock();
        std::this_thread::sleep_for (std::chrono::milliseconds(1));
        mut.lock();
    }

    tokens--;
    mut.unlock();
}

void Semaphore::V() {
    mut.lock();
    tokens++;
    mut.unlock();
}
function:

C++ code:
std::mutex mutex;

void f() {
    mutex.lock();//sem->P();
    for(int i = 0; i < 1000; i++) {
        k++;
        l++;
        y += k - l;
    }
    c++;
    mutex.unlock();//sem->V();
}
From all the documentation and examples I'd think this is how a mutex works, but I still get stuff like this:

code:
Without atomic: 0
With atomic: 1268752
Tokens: 1
Completed threads: 1000
Note: even when I use the semaphore I get Tokens: 1.

E: Maybe if two threads are waiting at mut.lock() and the mutex is unlocked, both threads are released? If this is the case, how would you go about avoid this?

Joda fucked around with this message at 22:29 on Apr 23, 2015

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
No, the result I posted is from a run with mutex.lock()/unlock().

E: If it matters, it's compiled with g++ 4.8.1 with argument -std=c++11 and nothing else. Target is Linux x86_64.

Joda fucked around with this message at 22:44 on Apr 23, 2015

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
std::mutex is part of the C++ standard library, so lpthread shouldn't matter as far as I know (apparently I'm wrong.) However, I did try and use a pthread mutex in stead and now it works. Is std::mutex known to be wonky or linux systems or something? Or maybe C++11 hasn't been fully implemented in GCC 4.8.1?

C++ code:
static pthread_mutex_t pmutex = PTHREAD_MUTEX_INITIALIZER;

void f() {
    pthread_mutex_lock(&pmutex);

    for(int i = 0; i < 10000; ++i) {
        k++;
        l++;
        y += k - l;
    }
    c++;
    pthread_mutex_unlock(&pmutex);
}
code:
Without atomic: 0
With atomic: 0
Completed threads: 10000
Although, as soon as I spawn more than 10.000 threads it starts giving me a system error about a resource being temporarily available.

Still, something that throws an error is preferable to having undefined behaviour, so I'll take it,. thanks :D

EDIT: I tried adding -pthread (in stead of -lpthread) and now std::mutex works just fine. Isn't pthread an OS specific thing, and what is the difference between -pthread and -lpthread? I thought the l just stood for lib? Sometimes GCC completely baffles me :psyduck: Still, thanks a tonne for the help!

Joda fucked around with this message at 09:09 on Apr 24, 2015

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
CLion's debugging (which uses gdb) works almost as well as Visual Studio's. You can make break points, investigate all symbols in scope and you can even hover your mouse over symbols in your code to see their values when the program has stopped at a break point. (it also adds comments in your code showing the current break point value of symbols at their declarations.) I'm not sure what your options to get CLion is at the moment unless you're a student, but at the very least there's a 30 day trial period. I'm pretty sure you can get it for free for non-commercial applications though.

This is debugging with CLion in action:



Honestly I'm liking it more the more I work with it. It's super easy to set up too, as long as you make sure your gdb version corresponds to your gcc version (this should be automatic if you just use your standard repos versions.)

One thing I'm missing is some automatation for investigating STL containers like vectors, since browsing through iterators to find the actual values can be a pain in the rear end.

E: You can actually get full-blown VS + MSVC for Linux now? I thought I heard something like that, but all I could find was Visual Studio Code, which seemed like it was geared more towards net developers.

Joda fucked around with this message at 20:56 on May 2, 2015

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe

MrBadidea posted:

I want the poo poo out of this for Visual Studio. How many limbs is this going to cost me???

An individual license is €99 (I imagine it's the same in USD.) Free for educational/open source purposes. To my knowledge, though, the Windows version requires GCC (through MinGW or Cygwin) and won't work with MSVC.

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
If I wanted to have a collection of data of indeterminate type, I feel like the least awful solution should be one involving templates (like I'd have a map of pointers to a templated object, and then the receiver will know, based on the key, what type of data to expect.) My current implementation uses polymorphism, so I have a subclass for every type of data I want to pass around, but like I said it feels like I should be able to solve it with templates.

My problem is that when I try to use templates for this, and want a map of foo<T>* I have to provide the type of data when initialising the map. How would you do something like this, so I only have to provide type when I add an element? Is it even possible?

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
I'm trying to refactor a messaging system I made a while ago to use templates in stead of having to define a new class for every type of data I want to send. I'm getting linker errors, though, and I'm not really sure why. I tried defining specifically what template instances it should generate but I get some error about incomplete types? If I define stuff in the header file I get an error about redifinitions of functions, even though I have a header guard. Can someone tell me what I'm doing wrong here?

Message.h
C++ code:
class Message {
public:
    Message();
    Message(messageType type);

    template<typename T>
    T extractMsgData();

    const messageType type;
    bool kill = false;
};

template<typename T>
class DataMessage : public Message {
public:
    DataMessage(messageType type, T data);

    T data;
};
Message.cpp
C++ code:
Message::Message(messageType type) :
type(type)
{

}

Message::Message() :
type(NO_TYPE)
{

}

template<typename T>
T Message::extractMsgData() {
    return static_cast<DataMessage<T>*>(this)->data;
}

template<typename T>
DataMessage<T>::DataMessage(messageType type, T data) :
Message(type),
data(data)
{
}

//specific templates
template class DataMessage<glm::vec2*>;
template class DataMessage<glm::vec3>;
template class DataMessage<glm::vec2>;
template class DataMessage<std::string>;
template class DataMessage<std::string*>;
template class DataMessage<float>;
E: Also, does someone know how I can do either compile time or runtime checks of the DataMessage cast? I want to check if the type I'm casting to is actually what is at the pointer address, in stead of it giving me a non-descript runtime error if I try to ectract something other than what the message contains.

Joda fucked around with this message at 18:46 on Aug 2, 2015

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
Alright, thanks. I tried implementing the functions in the header and now it works for some reason. Does implementing non-member functions in headers cause problems with multiple includes or something, because that is the only difference from last time I tried.



Sex Bumbo posted:

It might sound dumb, but short of changing your approach to messages, having an enum to store the type might be preferable.

Consider: If you pass a message pointer around, any strategy that involves polymorphism is going to hit a lookup into a vtable. E.g. you could use a dynamic_cast to make sure you're casting into something valid, which is probably what you were asking for. This involves a type check which, best case, isn't going to be much different than an enum comparison and worst case will have to fetch memory likely outside of cache.

Or to put another way, if you were implementing this in assembly, there's no real way you can have a type-checked homogenous message that's compile time safe or runtime safe without passing extra data around.

messageType is already an enum in Message.h that contains all the types of messages I might want to send around. Every type has a specific type of data that I intend to send with it, but this is not enforced and I'm not sure if/how I can do that. I'm pretty sure it won't be a problem for me, but part of me feels like it's against good coding practice or something, since nothing is stopping someone from sending, say, a WINDOW_RESIZE_MSG (which is meant to get a vec2) as DataMessage<std::string>, or have the receiver try and extract the data with extractMsgData<float>() or something.

E: I was looking into dynamic_cast, but my understanding was that it only works from subclass to superclass and not the other way around?

Joda fucked around with this message at 02:45 on Aug 3, 2015

Adbot
ADBOT LOVES YOU

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
Why would I be getting an internal compiler error on a piece of code I've compiled with the exact same compiler hundreds of times before? I'm using g++ 4.9.something on MinGW64. On my current project I'm suddenly getting errors on an include of <vector> that seems to refer me to their implementation of initialiser lists.

It's telling me to file a bug report to the mingw team, but I'm not sure how it can suddenly become bugged from one day to the next. My code base is literally the same as I succesfully compiled on the same system just two days ago.

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