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
Thug Bonnet
Sep 22, 2004

anime tits ftw

Jo posted:

Thanks for the responses.


I did not know this. I thought display lists were faster because they were 'compiled' and stored.

Static VBOs, display lists, and other glDrawArrays() calls will be similarly speedy but proper buffer objects let you do cool things like make dynamic buffers that can be temporarily bound to local memory and manipulated (this comes in multiple flavors depending on how often you want to manipulate them). You can also obviously make then static, too.

Another advantage is that when you request memory on the video device you can just grab enough for all your mesh information (vertices, normals, colors, etc) and stack them end-to-end in the buffer. When you set up your pointers for glDrawArrays() you can use the offset within the VBO and you're in business!

You can also use PBOs to store texture data, which is nice because then you can stream it back into a texture right before you draw. This can be cool because then you can use the same methods that you would use for a dynamic VBO to manipulate your texture (by hand, animated textures, etc).

Adbot
ADBOT LOVES YOU

Thug Bonnet
Sep 22, 2004

anime tits ftw

What is a reasonable way to read a series of lines of unknown length that contain variables of mixed types from a text file? I have read that fprintf() can cause problems, and then there's the issue of buffer size. I could go ahead and make the buffer the size of the entire file for safety but that seems silly. On the other hand, seeking to the next newline and realloc()-ing the buffer for every line seems costly.

Lets assume the text file looks like this

code:
var1=1.0
var2=foo
..
e: In C, so no streams for me.

Thug Bonnet fucked around with this message at 22:10 on Mar 2, 2008

Thug Bonnet
Sep 22, 2004

anime tits ftw

Avenging Dentist posted:

You'd only need to realloc when the next line is longer than the current one. If you pick a decent starting buffer length, there shouldn't be much reallocation.

Good point! Is that a reasonable thing to do then? I'm pretty new with file i/o so I honestly don't know.

Thug Bonnet
Sep 22, 2004

anime tits ftw

Is it possible to examine the memory space a program resides in from within the program?

Thug Bonnet
Sep 22, 2004

anime tits ftw

ShoulderDaemon posted:

...yes, programs can read their own memory. But that can't possibly be what you mean to be asking. What are you trying to do?

No, that's what I'm asking! :) I'm just kind of curious, honestly. But how would the program know "where it is" in memory, how large it is, etc. Also, I assume it's not necessarily contiguous..

Thug Bonnet
Sep 22, 2004

anime tits ftw

HB posted:

Each process's address space is identical*, so that information isn't really useful to anything other than the kernel. If such a query existed, it would return identical results for all processes on the computer. A program generally doesn't have or need the ability to know what physical addresses its virtual pages are at, especially because those may change literally from instruction to instruction under a modern virtual memory system.



*Unless ASLR is enabled, but again, that's only the OS's concern.

Identical in what sense?

Thug Bonnet
Sep 22, 2004

anime tits ftw

HB posted:

The largest possible address depends on which system you're on. On Win32 you get 2GB of virtual space; the largest valid pointer value is UINT_MAX/2. On 32-bit OS X and other Unixes you get somewhere between that and 4GB. On a 64-bit architecture the limit is so high it's not worth calculating.

Is it possible to know the size at any given time, though? For example would it be possible to just create a memory dump as a program is running? I'm trying to think of a "hello world" of memory dumps, but I'm not sure where to begin.

Thug Bonnet
Sep 22, 2004

anime tits ftw

chutwig posted:

Okay, I understand my first mistake; forgetting that the pointer is its own type with a different size from what it points to.

Yeah, you're getting confused between the pointer's value versus the value of what it's pointing at. The pointer just contains an address (4 bytes worth) of a location in memory. That location in memory is hopefully something useful (a variable, for instance). Remember that the pointer is not the value of that variable, it's just a reference to it. You can change what it's pointing at at any time.

For example:
code:
#include <stdio.h>

struct data{
	int foo;
	float bar;
	long baz;
};

int main(){
	printf(
		"\nDeclare an int variable and a pointer to an int, then we set the int pointer to the address of ('&') the int variable.\n\n"
		);

	int i, *ip;
	ip = &i;

	i = 10;
	printf("Value of i: %d\n", i);
	printf("Location of i in memory: %#X\n", ip);

	printf(
		"\nLet's change the value of i by dereferencing pointer ip by using the '*' operator\n\n"
		);

	*ip = 12;
	printf("Value of i: %d\n", i);
	printf("Value of i (via dereferencing our pointer): %d\n", *ip);

	struct data dataVar;
	struct data * dataPointer;

	printf(
		"\nThe same is true of structs\n\ndataVar size: %d\ndataPointer (pointer) size: %d\ndataPointer (value) size: %d\n", 
		sizeof(dataVar), sizeof(dataPointer), sizeof(*dataPointer)
		);
	return 0;
}

Thug Bonnet
Sep 22, 2004

anime tits ftw

Mikey-San posted:

The size of a pointer is architecture-dependent. Under 32-bit, a pointer is 4 bytes; on 64-bit, a given memory location is 8 bytes long.

True! :)

Thug Bonnet
Sep 22, 2004

anime tits ftw

Smackbilly posted:

Agreed. Pointers are hard to avoid making mistakes with (memory leaks, etc). They aren't hard to understand. A lot of new programmers don't pick up on that distinction when some people bitch about pointer problems.

Well to be fair if your first language isn't strongly-typed and you come to C later on it can get hairy and that may trickle down to pointers, too. Also, the concept of pass-by-reference versus pass-by-value is more obfuscated in other weakly(okay fine, "dynamically")-typed languages, though in essence I think it's the same issue. People think pointers are difficult (I thought so too), but the trick is they are simple, just deceptively so.

Thug Bonnet
Sep 22, 2004

anime tits ftw

Is it possible to use the initialization list of an objects constructor to assign members of a struct (that's a member of the object)? This type of thing is giving me problems:

init_test.h
code:
struct test_struct{
	int struct_member;
};

class TestObject{
	struct test_struct ts;
	public:
		TestObject(int _struct_member);
};
init_test.cpp
code:
#include "init_test.h"

TestObject::TestObject(int _struct_member)::ts.struct_member(_struct_member);

Thug Bonnet
Sep 22, 2004

anime tits ftw

prolecat posted:

I'm 99% sure you can't do that, but I've never tried it. What you can do is give your struct a constructor and call that in the initialization list:

code:
struct test_struct{
    int struct_member;
    test_struct(int _struct_member) : struct_member(_struct_member) {}
};

class TestObject{
    struct test_struct ts;
    public:
        TestObject(int _struct_member);
};

TestObject::TestObject(int _struct_member) : ts(_struct_member) {}

That is super clever, but it's not my struct :(

Thug Bonnet
Sep 22, 2004

anime tits ftw

Avenging Dentist posted:

But still what? Always write code that's easier to read first, and if it turns out to be slow for whatever reason, then optimize it.

Well then putting aside the initialization list it seems like just doing assignment in the constructor would be more readable?

Thug Bonnet
Sep 22, 2004

anime tits ftw

On Linux, using Ncurses' getch() blocks by default, waiting for input, on Windows using Cygwin it doesn't for some reason. Anyone know why?

I tried specifying nocbreak() for "cooked mode" and it didn't seem to help.

code:
#include <ncurses.h>

int main(){
	initscr();
	printw("Hello world!");
	refresh();
	nocbreak();
	getch();
	endwin();

	return 0;
}

Thug Bonnet
Sep 22, 2004

anime tits ftw

Is it possible to forward declare derived child classes? I would think no, but it seems to make taking full advantage of covariant return types pretty difficult if your base classes are dependent on one another.

foobase.h
code:
#ifndef _foobase_h_
#define _foobase_h_

class BarBase;

class FooBase{
	virtual BarBase * returnBar(BarBase * _bar);
};

#endif
barbase.h
code:
#ifndef _barbase_h_
#define _barbase_h_


class FooBase;

class BarBase{
	virtual FooBase * returnFoo(FooBase * _foo);
};

#endif
If I then want to overload those methods using covariant types, obviously there's going to be a problem since I can't forward declare the lineage of the derived types, and I can't use their includes, since it would be circular. The #ifndef will keep it from wigging out the compiler, but I'll still end up with things undefined.

fooderived.h
code:
#ifndef fooderived_h_
#define fooderived_h_

#include "foobase.h"

class FooDerived: public FooBase{
	BarDerived * returnBar(BarBase * _bar); // Can't define BarDerived
};

#endif
barderived.h
code:
#ifndef barderived_h_
#define barderived_h_

#include "barbase.h"

class BarDerived: public BarBase{
	FooDerived * returnFoo(FooBase * _foo); // Can't define FooDerived
};

#endif

Thug Bonnet
Sep 22, 2004

anime tits ftw

Avenging Dentist posted:

Why would you think that class FooDerived; is bad? It's 100% legal.

Forward declaring FooDerived is just fine, but the problem is that as far as I can tell any notions of lineage require definition, not just declaration, so it can't be used to redefine FooBase * BarBase::returnFoo(FooBase * _foo) as FooDerived * BarDerived::returnFoo(FooBase * _foo)

Thug Bonnet
Sep 22, 2004

anime tits ftw

Avenging Dentist posted:

Ah, I see what you mean by "covariant return types". Those are strictly illegal in C++ (as well they should be, since they open up a can of worms with respect to overloading). That's just not how C++ works; apparently it's legal in Java, but I honestly don't see the point anyway.

They're legal in C++ according to the spec though apparently it was a long time before MSVC/GCC supported them. I can see the can of worms they open, but on the other hand they can also enforce some safety too. They were intended to reduce the need for dynamic_cast-ing, but they don't really.

I figured I would be fancy and use them, but that's why I was surprised since they are apparently way less useful than they were intended (and Bjorn says as much in "Design and Evolution of C++", but I hadn't had occasion to try them out until now.

I figured I must be doing it wrong, so that's seriously a bummer imo :(

Thug Bonnet
Sep 22, 2004

anime tits ftw

Avenging Dentist posted:

I got it working, if you care. Here's the trick:

code:
class nil{};

template<typename T,typename Base = nil>
class wrapper : public wrapper<Base>
{
public:
	wrapper() {}
	wrapper(T *p) : wrapper<Base>(p) {}
	T * get() { return (T*)wrapper<Base>::p; }
};

template<typename T>
class wrapper<T,nil>
{
public:
	wrapper() {}
	wrapper(T *p) : p(p) {}
	T * get() { return p; }
protected:
	T *p;
};
Use wrapper<Foo>* and wrapper<FooDerived,Foo>* as return types (obviously this requires more in the way of memory management, but what can you do :()

This might not even be strictly valid C++, I only tested it in MSVC 8. If you want all the source files, I'll send them to you, but the above is the relevant bit.

Yeah, I'm pretty sure that's not valid, but it's quite a hack, seriously that's clever :)

Thug Bonnet
Sep 22, 2004

anime tits ftw

Is the find method for std::string supposed to ignore '\0'?
This doesn't work:
code:
char cstr[] = {'t','e', 's', 't', '\0', 'f'};
std::string cppstring += str;
int pos;

if((pos = client_message.find('\0')) != std::string::npos)
	std::cout << pos << std::endl;

Thug Bonnet
Sep 22, 2004

anime tits ftw

Avenging Dentist posted:

Strings are null-terminated, you know. :psyduck:

Yes, I know ;)

I'm recieving multiple messages over a socket that are terminated with '\0', and I need to be able to split them up on their boundries.

Thug Bonnet
Sep 22, 2004

anime tits ftw

Avenging Dentist posted:

Put it in a vector or something. Appending a string with nulls in it isn't even going to do what you want, since it'll terminate at the first null.

Ah, gotcha, didn't realize it stopped appending at '\0' too. Thanks!

Thug Bonnet
Sep 22, 2004

anime tits ftw

Is the common solution here to end your messages with some other control character? \n?

Thug Bonnet
Sep 22, 2004

anime tits ftw

Avenging Dentist posted:

Do what?

I assume set playername from the constructor argument, the question being should you use an initialization list, and the answer being yes.

Thug Bonnet
Sep 22, 2004

anime tits ftw

GrumpyDoctor posted:

And yes, that was the problem. For some reason GSTTypes.h doesn't include everything it needs. I am still learning my way around some of these compiler errors I guess!

Are you sure you just don't have your includes set up in a different directory structure than GSTTypes.h is expecting?

Thug Bonnet
Sep 22, 2004

anime tits ftw

floWenoL posted:

Surely you have access to the bitmap in memory before you dump it to disk? CImg has constructors that take in a raw bitstream and reads it given dimensions, stride, and color format. It looks like the Win32 API functions return a 24-bit bitmap, so it should be fairly straightforward to get the necessary params from the bitmap header and pass them to CImg.

Yeah you can get the DIB rather than write it to disk iirc.

Thug Bonnet
Sep 22, 2004

anime tits ftw

What is the proper way to enforce type safety via argument with polymorphic classes? For example what if in the following code I wanted to make a derivative of my container class that would only take B* as the argument to add(), rather than ACont which takes A*.

code:
#include <list>

class A{
	public:
		A(){};
		virtual ~A(){};
};

class B: public A{
	public:
		B(){};
		~B(){};
};

class C: public A{
	public:
		C(){};
		~C(){};
};

class Cont{
	public:
		Cont(){};
		virtual ~Cont(){};
		virtual void add(A*)=0;

	protected:
		std::list<A*> l;

class ACont: public Cont{
	public:
		ACont(){};
		~ACont(){};

		void add(A* a){
			l.push_back(a);
		};

};
int main(){
	ACont * ac = new ACont();
	A* b = new B();
	A* c = new C();

	ac->add(b);
	ac->add(c);

	return 0;
};
For example:
code:
class BCont: public Cont{
	public:
		BCont(){};
		~BCont(){};

		void add(B* b){
			l.push_back(b);
		};
};
The problem here is obviously making void Cont::add() virtual doesn't help because the arguments are part of the prototype, e.g. void add(A*) != void add(B*) so it won't be properly overridden (or in this case satisfy the requirement to implement void add(A*) ).

Thug Bonnet fucked around with this message at 05:22 on Feb 9, 2009

Thug Bonnet
Sep 22, 2004

anime tits ftw

Dang, I was just combing through c++-faq-lite. I had a feeling it had the answer, I just couldn't find it.

I'd really like to avoid templates for this for a number of reasons. I guess I need to re-think it. I'm glad to know I wasn't just missing something, though :)

Avenging Dentist posted:

Depending on your requirements, you may also choose to remove Cont::add and have add only appear in the subclasses, thus requiring you to use a (A|B)Cont if you want to insert objects.

But this would mean I can't guarantee you can add() in some instances (for example passing the interface pointer).

Thug Bonnet fucked around with this message at 06:24 on Feb 9, 2009

Thug Bonnet
Sep 22, 2004

anime tits ftw

ShoulderDaemon posted:

You simply can't safely add anything given an interface pointer. You're only allowed to add something that's the same class, but given only the interface you don't know what class that is, so there's no way you can add anything. This is the same reason a vector of Cars isn't a vector of Vehicles.

Ah, a lightbulb just went on. This makes things marginally more complicated then :(

Thug Bonnet
Sep 22, 2004

anime tits ftw

Avenging Dentist posted:

A really, really hacky option would be to ensure that you have the correct type by using a dynamic_cast, but I really don't recommend that. (Also it obviously only works at runtime).

Well i mean its not THAT hacky, and in fact has been recommended to me. But it just feels.. dirty. And doesn't really help all that much because what, you just silently ignore bad input? Not a wonderful solution.

Thug Bonnet
Sep 22, 2004

anime tits ftw

Obviously this is eating more memory, but is safer re: the bag-of-apples is not-like bag-of-fruit. Is this legit?

e: see below

Thug Bonnet fucked around with this message at 02:47 on Feb 13, 2009

Thug Bonnet
Sep 22, 2004

anime tits ftw

Avenging Dentist posted:

I don't see what you're even trying to do with this??

Oh dang, sorry. I've got my head so far into it I didn't realize it didn't make much sense without context ;)

The idea is that there is a hierarchy of types, each more specific than the last, and containers that operate on these types independently. This is Re: this post. The intent is to avoid potentially unsafe casting, and the ability to cast and dereference to an improper type as seen in the C++-Faq-Lite here.

I had meant to re-name things to make this more clear, we can use the car-lot analogy.
code:
#include <list>
#include <iostream>

class Vehicle{
	public:
		Vehicle(){};
		virtual ~Vehicle(){};
};

class Car: public Vehicle{
	public:
		Car(){};
		virtual ~Car(){};
};

class Porsche: public Car{
	public:
		Porsche(){};
		virtual ~Porsche(){};
};

class VehicleDealership{
	public:
		VehicleDealership(){};
		virtual ~VehicleDealership(){};

	protected:
		void addVehicle(Vehicle* v){
			l.push_back(a);
		};

	private:
		std::list<Vehicle*> l;
};

class CarDealership: public VehicleDealership{
	public:
		CarDealership(){};
		virtual ~CarDealership(){};

	protected:
		void addCar(Car* c){
			l.push_back(c);
			addVehicle(c);
		};

	private:
		std::list<Car*> l;

};

class PorscheDealership: public CarDealership{
	public:
		PorscheDealership(){};
		virtual ~PorscheDealership(){};

		void add(Porsche* p){
			addPorsche(p);
		};

	protected:
		void addPorsche(Porsche* p){
			l.push_back(p);
			addCar(p);
		};

	private:
		std::list<Porsche*> l;

};

int main(){
	PorscheDealership* pdp = new PorscheDealership();
	Porsche* pp = new Porsche();

	PorscheDealership->add(pp);

	return 0;
};

Thug Bonnet
Sep 22, 2004

anime tits ftw

Avenging Dentist posted:

That still makes no sense because none of your collection base classes even have a public interface, so it's not clear what problem you're actually trying to solve here.

EDIT: I mean actual, real-world problem here.

In practice the base classes would be purely virtual, I just didn't want to crap up the post and make a huge(r) block of code. The intent is that only the top-most derived class (from Vehicle and VehicleDealership) would be intended to actually have public methods, and would thus be the final derivation.

This is to prevent the other implementation (from my previous posts), in which only the base-most class would have a list to the base-most interface. In this case, VehicleDealership (would have a list of Vehicle*), and the classes that derive from it (for example, CarDealership, etc) would be responsible from casting properly from the list in VehicleDealership. The other wrinkle being that a View may be observed by more than one Presenter of different types.

If you wanted to Porsche get(); from the PorscheDealership, previous I was requiring the implementation to cast up from the VehicleDealership's list of Vehicle* to a Porsche*. So now, while I have multiple lists at each level of interface, it's safer in theory because it avoids casting and the final derivation can be a bit more type-safe in what it add()s.

Ultimately the purpose is to to have a loosely-coupled MVP style "Passive-View" relationship in which a Presenter class drives a View class without knowing anything more specific about it than it needs. I.E. GamePresenter drives a GameView, but any particular GameView may be of a more specific type like an OpenGlGameView, CursesGameView, etc.

Thug Bonnet
Sep 22, 2004

anime tits ftw

Plorkyeran posted:

What does an abstract class with no public interface give you over just not inheriting at all? void doStuff(VehicleDealership vd) { ... } can't actually do anything with vd.


It'd fail to compile because there is no add(Car *)?

In practice there would be public interfaces for the base classes, sorry that wasn't clear, I was just illustrating the hierarchy. And it's okay if the lists in the base classes are out of sync with one another. For example, there could be a GermanCarDealership which inherits from both PorscheDealership and VolkswagenDealership, in which case the list of Car* in CarDealership will have more elements than either the list of Porsche* in PorscheDealership or the list of Volkswagen* in VolkswagenDealership. Because of this we can safely call public methods at any level of specificity (Vehicle, Car, Porsche, Volkswagen) without casting, we can enumerate our Porsche*s without a dynamic_cast, etc.

As far as how this is important to my GamePresenter and GameView, they inherit from Observer and Subject respectively. I would like those two base classes to handle everything that needs to be done for the Observer-Subject relationship: Subjects may be observed by any number of Observers, and handle the basic methods they call on one another for basic messaging and registration. But in certain cases I would like to prevent some specific couplings of Observer-Subject in cases where it wouldn't make any sense, and do so without relying on RTTI. It wouldn't make much sense for a GamePresenter to observe a WindowView, for example.

Thug Bonnet fucked around with this message at 05:44 on Feb 13, 2009

Thug Bonnet
Sep 22, 2004

anime tits ftw

TSDK posted:

Your root problem is that you're trying to apply real-world intuition about the relationships between different objects to class design and inheritance. Just because a Car is-a type of Vehicle in the real world, it doesn't hold that mirroring this directly into a class hierarchy will result in a good (or even workable) design for what you're trying to write. This holds just as true for GamePresenter etc...

Read through this (21.6 through to 21.11):
http://www.parashift.com/c++-faq-lite/proper-inheritance.html
and make sure you understand the substitution principle of inheritance before proceeding.

I thought I had a pretty-good handle on the is-a problem, especially with regard to the circle/ellipse example. Even given the circle/ellipse example it would seem that as far as a hierarchy goes that you can use Vehicle->Car without too much problem, as long as you don't assume anything in Vehicle that may dilute Car. You wouldn't want an openDoor() method in Vehicle, for example, since lots of vehicles don't have doors.

What about the Vehicle->Car (or GameView-GamePresenter) relationship do you feel is inherently improper?

Thug Bonnet
Sep 22, 2004

anime tits ftw

TSDK posted:

However, the substitution principle says that wherever you have a Base *, then it must be acceptable to pass a Derived *. The container classes are heading towards breaking that principle, and everything else from then on is just a sticking plaster.

That's what I was working toward, the multiple lists is just to prevent casting up, or using an enum, but I'll look at enums again and see if it makes more sense to me having re-read the faq-lite OO section.

Thug Bonnet
Sep 22, 2004

anime tits ftw

What is a reasonable way to express a many-to-many relationship between objects of differing type with the ability of an object of either type to find out about it's relationships?

There should be a mediator involved between any given relationship, but how would I accomplish the actual structure without just having lists that need traversing?

For example

[ObjectA]<-->[Mediator]<-->[ObjectB]

Either object would be need to be able to query the mediator and find which objects are claiming a relationship. Ideally this would be similar to the STL::multimap that can be queried by either key or value.

Thug Bonnet
Sep 22, 2004

anime tits ftw

Avenging Dentist posted:

Look at Boost.Bimap: http://www.boost.org/doc/libs/1_38_0/libs/bimap/doc/html/index.html

Beautiful, thanks! Is that type of structure commonly known as a "bitmap"? I haven't seen it used that way before..

Thug Bonnet
Sep 22, 2004

anime tits ftw

Avenging Dentist posted:

Bimap, no T.

Yow, thanks again

Thug Bonnet
Sep 22, 2004

anime tits ftw

Is there a common means of generating a public interface header for a library from multiple headers? For example my library has multiple source files, and multiple headers, and ultimately I'd like to have a single header to include that describes the interface rather than the handful of separate headers.

Adbot
ADBOT LOVES YOU

Thug Bonnet
Sep 22, 2004

anime tits ftw

Adhemar posted:

Make a header that includes the other headers?

That's one solution, but it's not very pleasant. I know there are utilities to do this, I just don't know what they are.

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