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
Absurd Alhazred
Mar 27, 2010

by Athanatos
Wow, they sure did a number on C since I was a kid. Then again, C++ looks very different from what I got in undergrad, too.

Adbot
ADBOT LOVES YOU

Nalin
Sep 29, 2007

Hair Elf

cheetah7071 posted:

while I am still deeply curious how I managed to get a situation where the linker was complaining about being unable to find a file I wasn't trying to link to, I switched to vcpkg and everything works now so good riddance, I guess

Boost will use #pragma comment(lib, ...) when the build system is MSVC (or Borland!) This means that the boost headers that you use will auto-link the appropriate boost library. If your build system doesn't install the libs with the correct file name, or you don't pass in #defines to control the auto-linking, you'll have problems.

See also: https://www.boost.org/doc/libs/1_63_0/boost/config/auto_link.hpp

Nalin fucked around with this message at 22:28 on Nov 20, 2022

Xarn
Jun 26, 2015
oh god, I forgot about that misfeature

Ihmemies
Oct 6, 2012

So, I got feedback about a project and it said I need to initialize class variables. I was like ?????

I searched for a reason and apparently it is this:



If I have a map like this in class:

C++ code:
map<string, shared_ptr<Chapter>> idstore
How do I properly intialize it? I don't want to add any garbage to it which I have to get rid of later. Is this ok instead on the class header?

C++ code:
map<string, shared_ptr<Chapter>> idstore = {}
Or maybe this in Class constructor?

C++ code:
idstore = {}

Twerk from Home
Jan 17, 2009

This avatar brought to you by the 'save our dead gay forums' foundation.

Ihmemies posted:

So, I got feedback about a project and it said I need to initialize class variables. I was like ?????

Use initializer lists in your constructors, like this: https://en.cppreference.com/w/cpp/language/constructor

Ihmemies
Oct 6, 2012

Twerk from Home posted:

Use initializer lists in your constructors, like this: https://en.cppreference.com/w/cpp/language/constructor

Well I have only one constructor and there's nothing in it. I just want to avoid that "intialize your class variables, minus 5 points" message I will get. I don't want to do anything complicated. I don't understand really a word about what that page says :v: That one class variable I use must be initialized properly, I just have to figure out how to do it. I don't want to add any data to the variable (map). I just want that the map exists, and is ready if someone ever wants to add data to it later.

Zopotantor
Feb 24, 2013

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

Ihmemies posted:

So, I got feedback about a project and it said I need to initialize class variables. I was like ?????

I searched for a reason and apparently it is this:



If I have a map like this in class:

C++ code:
map<string, shared_ptr<Chapter>> idstore
How do I properly intialize it? I don't want to add any garbage to it which I have to get rid of later. Is this ok instead on the class header?

C++ code:
map<string, shared_ptr<Chapter>> idstore = {}
Or maybe this in Class constructor?

C++ code:
idstore = {}

Using an uninitialised variable is not what I would consider a type safety issue.

As for your question, the default constructor of a class should normally(*) create valid, fully initialised objects. This applies to many (most?) of the container classes in the standard library. For a map you don’t need the initialiser (but it probably doesn’t hurt to write it).



* it’s C++, so of course this is not always the case. For example, std::array<T,N> requires an initialiser, unless the type T itself guarantees that its default constructor creates fully initialised objects

OddObserver
Apr 3, 2009

Zopotantor posted:

Using an uninitialised variable is not what I would consider a type safety issue.



Uninitialized bools say hi, and worm their way into to your nightmares. Then the rest of undefined behavior pops in for a chat...

But yeah, in real world, as was stated above, the map doesn't need an initializer and ints/bools/doubles, etc., do; in your class? Ask your TA/professor/teacher as appropriate.

Subjunctive
Sep 12, 2006

✨sparkle and shine✨

Zopotantor posted:

Using an uninitialised variable is not what I would consider a type safety issue.

I think I would. A type system guarantees that, if you play by the rules, all values have the properties of their specified type. In the case of `bool`, that means "can only have values 1 or 0 when converted to int" and "can be exhaustively tested by comparing to `true` and `false`". If the type system holds, this can't assert:

code:
bool b = something();
assert(b == true || b == false);
Similarly, reading an uninitialized pointer means that the type definition's guarantees about its referent likely don't hold.

cheetah7071
Oct 20, 2010

honk honk
College Slice
For proper classes, instead of built-in types, they'll be constructed using the default constructor if you don't specify otherwise. Either they just wanted to to clarify that you were using the default constructor as like, a coding clarity thing, or they were talking about a member other than that map.

Zopotantor
Feb 24, 2013

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

Subjunctive posted:

I think I would. A type system guarantees that, if you play by the rules, all values have the properties of their specified type. In the case of `bool`, that means "can only have values 1 or 0 when converted to int" and "can be exhaustively tested by comparing to `true` and `false`". If the type system holds, this can't assert:

code:
bool b = something();
assert(b == true || b == false);
Similarly, reading an uninitialized pointer means that the type definition's guarantees about its referent likely don't hold.

OK, that makes sense. Enums would have the same problem.

Ihmemies
Oct 6, 2012

cheetah7071 posted:

For proper classes, instead of built-in types, they'll be constructed using the default constructor if you don't specify otherwise. Either they just wanted to to clarify that you were using the default constructor as like, a coding clarity thing, or they were talking about a member other than that map.

I had 2 uninitialized maps in the class header file. No other variables, only methods. They can’t possibly mean anything else.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Ihmemies posted:

I had 2 uninitialized maps in the class header file. No other variables, only methods. They can’t possibly mean anything else.
Again, given how godawful the things you've shown us are, I 100% believe they are telling you to explicitly initialize a std::map member. You shouldn't have to, it's a dumb directive, but if it's what you have to do for the points, you can just treat it like you're working at a company with a stupid style guide, because this is exactly the sort of thing that shows up in stupid style guides.

Ihmemies
Oct 6, 2012

Finally a friend said what I must do.

If I create a vector like vector <string> to_sort; I must do vector <string> to_sort = {}; instead. If I create a map like map<string, shared_ptr<Chapter>> idstore; I have to do map<string, shared_ptr<Chapter>> idstore = {}; instead.

So the magic thing I must do is to add this after every vector and map to fix the problems:

C++ code:
= {};
I am glad I finally found the definitive answer I am looking for :ms:

Edit: and now I maybe finally perhaps understand? I must list instead all the class variables like this in the constructor, separated by ,

C++ code:
Book::Book() : running_id(0), idstore() { }
running_id is int and that 0 parameter sets it as 0... welp. I want back to python.

Ihmemies fucked around with this message at 11:32 on Nov 23, 2022

Xarn
Jun 26, 2015
do whatever you need to pass the course, but that's poo poo code if I ever saw one

Ihmemies
Oct 6, 2012

Xarn posted:

do whatever you need to pass the course, but that's poo poo code if I ever saw one

The only issue is that I don’t know what to do. So I just do whatever I can find and understand. There is tons of info I can’t seem to understand by myself, about c++. I think I now understand how that works what I just pasted here, but I don’t know or I don’t understand any other ways to initialise class variables in class constructor. I was told that initializing class variables as empty with = {} in class header is even worse.

Please teach me master.

Ihmemies fucked around with this message at 12:52 on Nov 23, 2022

leper khan
Dec 28, 2010
Honest to god thinks Half Life 2 is a bad game. But at least he likes Monster Hunter.

Ihmemies posted:

Finally a friend said what I must do.

If I create a vector like vector <string> to_sort; I must do vector <string> to_sort = {}; instead. If I create a map like map<string, shared_ptr<Chapter>> idstore; I have to do map<string, shared_ptr<Chapter>> idstore = {}; instead.

So the magic thing I must do is to add this after every vector and map to fix the problems:

C++ code:
= {};
I am glad I finally found the definitive answer I am looking for :ms:

Edit: and now I maybe finally perhaps understand? I must list instead all the class variables like this in the constructor, separated by ,

C++ code:
Book::Book() : running_id(0), idstore() { }
running_id is int and that 0 parameter sets it as 0... welp. I want back to python.

https://en.cppreference.com/w/cpp/language/default_initialization

That should probably default initialize.

In general, you want unordered_map instead of map, but it likely doesn't matter a whole lot for your class.

Ihmemies
Oct 6, 2012

leper khan posted:

https://en.cppreference.com/w/cpp/language/default_initialization

That should probably default initialize.

In general, you want unordered_map instead of map, but it likely doesn't matter a whole lot for your class.

So.. what should I do otherwise in my code? Something must be done otherwise since the way I initialise my class variables is apparently poo poo. Can you give me an understandable example? Thanks 🙏

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Ihmemies posted:

I was told that initializing class variables as empty with = {} in class header is even worse.
False, initializing simple values that don't vary by constructor in the class header is totally fine.

Also, things that default-initialize to empty don't have to be explicitly initialized at all.

Basically, your course is teaching you weird cargo-cult nonsense. When people say e.g. "that's poo poo code if I ever saw one" they're not knocking *your* code, they're talking about how bad the course is to push this bullshit on you. Since that's what you have to do to pass, write the poo poo code, it's not *wrong*, it's just pointlessly ugly because someone made a bad rule for your course.

Ihmemies
Oct 6, 2012

So what I’m doing is not really neccessary. And I am doing this only because for the sake of appearances, thank you.

more falafel please
Feb 26, 2005

forums poster

Ihmemies posted:

So what I’m doing is not really neccessary. And I am doing this only because for the sake of appearances, thank you.

Yeah, to be clear: it's always a good idea to make sure variables are initialized before use. However, the default construction of container classes like std::vector and std::map initializes them to reasonable defaults (an empty container).

Presumably your instructor just wants you to make that explicit, which is fine, I guess, it doesn't hurt anything, but it's a little silly.

go play outside Skyler
Nov 7, 2005


This thread is a nice example of why a lot of people hate C++.

I was also taught C++ the wrong way. Endless exercises of "which method overrides which" and dumb multiple inheritance problems.

After avoiding it for years I finally got a job where it was asked of me to write in modern C++ and boy, did I realize my teacher was bad. And how loving good C++ can be with its modern additions.

His courses basically stopped at C++98.

Ihmemies
Oct 6, 2012

Well I don't really hate c++. It feels like I make a lot less erros with c++ than with python. I've read about new c++ features and I use them when possible. I think it's quite nice language to use. Especially print() coming in c++23 should be great instead of this something + something + something or << something << something << something.

It's just that c++ has so much stuff to get code working, that it's hard to remember or understand everything.

giogadi
Oct 27, 2009

New print in c++23? What was wrong with printf?

nielsm
Jun 1, 2009



giogadi posted:

New print in c++23? What was wrong with printf?

Not type safe, not extensible.

Yes, lots of compilers have special magic that recognizes format strings and attempts to type check the arguments, but a native C++ implementation with constexpr logic can actually allow a pure implementation that isn't dependent on compiler magic and can also be extended by user code.

Ihmemies
Oct 6, 2012

Now I need to somehow learn to appreciate ANSI C. I need to print out numbers 1 7 11 13 17 19 23 29 31 37 41 43 47 49 53 59 61 67 71 73 77 79 83 89 91 97 in a loop. but the last one must have \n exactly after it, not allowed to print one space after it. My blood pressure is already rising. I guess I need to calculate the next number, and if there's no next number (after 97), I won't print a space after 97..

nielsm
Jun 1, 2009



Don't print the separator (space or newline) after each number. Print it before each number.

ultrafilter
Aug 23, 2007

It's okay if you have any questions.


nielsm posted:

Don't print the separator (space or newline) after each number. Print it before each number.

Just not the first one.

Ihmemies
Oct 6, 2012

Yes. I guess C forces to think. In python could just add it all to string and not print the last char of the string. Not so easy here..

cheetah7071
Oct 20, 2010

honk honk
College Slice
You could still do that it'd just be kind of inefficient

mobby_6kl
Aug 9, 2009

by Fluffdaddy

leper khan posted:

Per my previous post, everything but operator overloads, yes.
Yeah you're right :) The thread has been moving somewhat slowly so I didn't think to refresh it and read anything before :justpost:

Anyway, if anyone's curious how the story ends (I doubt it), I ran the updater though Cutter disassembler and decompiler which was luckily reasonably readable thanks to being pretty simple and having lots of debug messages.

This is the main function, and there's clearly a line that prints what I need (after the last comment) so it was pretty easy to backtrack


What I think is the hid_read_data function. Very helpfully, the debug messages will even tell you which API calls failed


It was going ok but eventually I got pretty frustrated, maybe I was screwing something up but sometimes it wouldn't let me rename variables and functions, and in any case I realized I could ever only get 60 bytes of data out of it without major edits. Instead after some searching, I found an awesome app called API Monitor which does exactly that. You can see the exact sequence and parameters of all the API calls, which made writing the code from scratch pretty trivial.


SetOutputReport tells it what you want, and the details are in the buffer. 0e is the report id, then 80,50 is the address to read, and 04 I guessed to be the bytes to request (correct). The next call updates the buffer with the output, 5 bytes of header and the data. Other than some boilerplate to get things initialized and find the right device, that's pretty much all:
C++ code:
		memset(buf, 0, sizeof(buf));

		// From sniffed call:
		//0e 20 00 00 05 01 80 50 00 04
		buf[0] = 0x0E; // Report id (14)
		buf[1] = 0x20; 
		buf[2] = 0x00;
		buf[3] = 0x00;
		buf[4] = 0x05;
		buf[5] = 0x01;
		buf[6] = 0x80; //address
		buf[7] = 0x50; //address
		buf[8] = 0x00;
		buf[9] = 0xFF; // 04 bytes? let's try more

		res = hid_write(handle, buf, 65);
		if (res < 0) {
			printf("Unable to write()/2: %ls\n", hid_error(handle));
		}

		//read back configuration
		do {
			if (hid_get_input_report(handle, buf, 65)) {
	...
so yeah... not that much of a programming project :v:

Ihmemies
Oct 6, 2012

So, the last subject in our C++ course is quick GUI apps with Qt.

A course provided template project won't comile. A fresh Qt widget project won't compile. It just says:

code:
21:09:51: Starting: "/usr/bin/make" -j6
g++ -Wl,-rpath,/home/seppo/Programs/Qt/6.3.1/gcc_64/lib -Wl,-rpath-link,/home/seppo/Programs/Qt/6.3.1/gcc_64/lib -o find_dialog  main.o mainwindow.o moc_mainwindow.o   /home/seppo/Programs/Qt/6.3.1/gcc_64/lib/libQt6Widgets.so /home/seppo/Programs/Qt/6.3.1/gcc_64/lib/libQt6Gui.so /home/seppo/Programs/Qt/6.3.1/gcc_64/lib/libQt6Core.so -lpthread -lGL   
/usr/bin/ld: cannot find -lGL: No such file or directory
collect2: error: ld returned 1 exit status
make: *** [Makefile:216: find_dialog] Error 1
21:09:51: The process "/usr/bin/make" exited with code 2.
Error while building/deploying project find_dialog (kit: Desktop Qt 6.3.1 GCC 64bit)
When executing step "Make"
21:09:51: Elapsed time: 00:00.
Wtf is "-lGL" :D It is really hard to find any info about whatever it is.

Edit. Well Google provided results instead of DGG. RIght after I figured out I better try another search engine. "apt install libgl1-mesa-dev"

Deep Dish Fuckfest
Sep 6, 2006

Advanced
Computer Touching


Toilet Rascal
Asked this somewhere else, was told this might be a better place: any good book to learn C++20? I learned C++11 reading "The C++ Programming Language" when the updated version covering that came out, but I've been away from C++ land for a while now so this is a good opportunity to refresh my memory and see what was added since then. There's no C++20 version of Stroustrup's book though so I need something else. Ideally something that goes into roughly the same amount of details and is as comprehensive as possible for the new stuff.

qsvui
Aug 23, 2003
some crazy thing
This may be of help: http://cppstd20.com/

I haven't actually read this book, but I've read the author's past works and I find he does a good job of covering things.

Deep Dish Fuckfest
Sep 6, 2006

Advanced
Computer Touching


Toilet Rascal
That's pretty much exactly what I was looking for, thanks.

Ihmemies
Oct 6, 2012

Now I need to make a Snake game with QT Widgets.

The game board must consist of squares, so I thought I'd make a bunch of squares with QGraphicsGridLayout and add square item objects to each grid. But, if I try to setLayout() a QGraphicsGridLayout inside a QWidget window, it says:

code:
game_window.cpp:41:15: Cannot initialize a parameter of type 'QLayout *' with an lvalue of type 'QGraphicsLinearLayout *'
qwidget.h:568:29: passing argument to parameter here
I have main menu, where I can open the game window with a click of a button. I can create a new QWidget window with the click of a button. Apparently QGraphicsWidget does't like to be a window, or otherwise needs something else. If I change QWidget to QGraphicsWidget a window won't open anymore when I click a button in the menu.

How do you create a QGraphicsWidget window in Qt? :v: I guess I need that to be able to use QGraphicsGridLayout. I just want a bunch of squares on screen, in a window, goddamnit.

Do I need to create a qgraphicswidget inside a qwidget so I can add some graphis grids? ? ? This is so complicated.

Ihmemies fucked around with this message at 16:17 on Nov 28, 2022

Volguus
Mar 3, 2009

Ihmemies posted:

Now I need to make a Snake game with QT Widgets.

The game board must consist of squares, so I thought I'd make a bunch of squares with QGraphicsGridLayout and add square item objects to each grid. But, if I try to setLayout() a QGraphicsGridLayout inside a QWidget window, it says:

code:
game_window.cpp:41:15: Cannot initialize a parameter of type 'QLayout *' with an lvalue of type 'QGraphicsLinearLayout *'
qwidget.h:568:29: passing argument to parameter here
I have main menu, where I can open the game window with a click of a button. I can create a new QWidget window with the click of a button. Apparently QGraphicsWidget does't like to be a window, or otherwise needs something else. If I change QWidget to QGraphicsWidget a window won't open anymore when I click a button in the menu.

How do you create a QGraphicsWidget window in Qt? :v: I guess I need that to be able to use QGraphicsGridLayout. I just want a bunch of squares on screen, in a window, goddamnit.

Do I need to create a qgraphicswidget inside a qwidget so I can add some graphis grids? ? ? This is so complicated.

Did you look at the documentation https://doc.qt.io/qt-6/qgraphicsgridlayout.html ? They have an example there on how to use it (add it to a QGraphicsScene ). Does this not work for you?

Ihmemies
Oct 6, 2012

Volguus posted:

Did you look at the documentation https://doc.qt.io/qt-6/qgraphicsgridlayout.html ? They have an example there on how to use it (add it to a QGraphicsScene ). Does this not work for you?

I have a mainwindow class, which is like a "launcher" for the game. Then I have game window, which uh I guess runs the game logic and tells the graphics what to do. Then the game_board class is actually which holds the graphics data?

So mainwindow -> gamewindow -> gameboard.

Gamewindow looks like this:

code:
#include "game_window.h"
#include "game_board.h"

#include <QGraphicsView>
#include <QDebug>

Game_window::Game_window(MainWindow *parent) :
    QWidget(parent, Qt::Window)
{
    //parent->hide();
    this->setStyleSheet("background-color: yellow;");

    QGraphicsScene scene;
    Game_board* window = new Game_board;
    scene.addItem(window);
    QGraphicsView view(&scene);
    view.resize(600, 600);

    parentWidget()->hide();
}

void Game_window::keyPressEvent(QKeyEvent* event) {
    if(event->key() == Qt::Key_Escape) {
        //qInfo() << "C++ Style Info Message";
        parentWidget()->show();
    }
}

Game_window::~Game_window()
{

}
And board like this:

code:
#include "game_board.h"
#include "square_item.h"

#include <QGraphicsGridLayout>

#include <QGridLayout>

Game_board::Game_board(QGraphicsWidget *parent) :
    QGraphicsWidget(parent, Qt::Window)
{
    QGraphicsGridLayout *grid = new QGraphicsGridLayout;

    Square_item* item = new Square_item;
    grid->addItem(item, 0, 0);

    item = new Square_item;
    grid->addItem(item, 1, 1);

    item = new Square_item;
    grid->addItem(item, 2, 2);

    item = new Square_item;
    grid->addItem(item, 1, 3);

    setLayout(grid);
}
Square_item is a QGraphicsItem which is supposed to hold the size and graphics etc. of the individual cell in the grid.. But I can't get anything to display and I have no idea why. Well I guess I just keep on experimenting and looking at the debugger, since it's really hard to figure out why nothing is being displayed on screen.

Volguus
Mar 3, 2009
Well, the first issue that i'm seeing is that the scene is destroyed after the Game_window constructor is finished. Game_window is a QMainWindow, right? Once the scene is created on the heap and you make the view the central widget of the main window, it should work. The parent of the view should be this.

Volguus fucked around with this message at 22:23 on Nov 28, 2022

Adbot
ADBOT LOVES YOU

Ihmemies
Oct 6, 2012

Volguus posted:

Well, the first issue that i'm seeing is that the scene is destroyed after the Game_window constructor is finished. Game_window is a QMainWindow, right? Once the scene is created on the heap and you make the view the central widget of the main window, it should work. The parent of the view should be this.

Well, no. I guess I can have many QMainWindows?

Like, the launcher where user can define the game area size, like x,y, set seed etc. is a QMainWindow. Then when user has figured out what kind of game he wants to play, it launches the game_window.

Anyways I made view and scene class variables, and changed the game_window from qwidget to qmainwindow. Then I can use setcentralwidget and it puts something to the screen, finally:

code:
Game_window::Game_window(MainWindow *parent) :
    QMainWindow(parent, Qt::Window)
{
    //parent->hide();
    this->setStyleSheet("background-color: yellow;");

    scene = new QGraphicsScene();
    Game_board* board = new Game_board;
    scene->addItem(board);
    view = new QGraphicsView(scene);
    this->setCentralWidget(view);

    parentWidget()->hide();
}{
It doesn't put what I want to screen, but at least it's somehow doing something.. which is more than before. Thanks!

I mean it displays a tiny window with nothing, but I can close it and move around. Not ideal, yet:

Ihmemies fucked around with this message at 22:58 on Nov 28, 2022

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