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
functional
Feb 12, 2008

If you make a separate C thread please make sure it's worth it first...I'm able to talk C/POSIX here with only a little added scrolling, which is absolutely fine. What I wouldn't want is the C++ programmers we depend on telling us to go back to the C-only thread that nobody contributes to.

Adbot
ADBOT LOVES YOU

Jethro
Jun 1, 2000

I was raised on the dairy, Bitch!

Ugg boots posted:

Pro-tip since you're new to the thread, Crazy RRRussian is a fakeposter who has been around these parts for a while under different names (Hexadecimal, Entheogen, ...)
I thought Crazy RRRussian is just a badposter, not a fakeposter.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
There's really not much of a difference.

Crazy RRRussian
Mar 5, 2010

by Fistgrrl
Haters gonna hate, and that was a serious question I had, not a fakepost! :(

Mr.Radar
Nov 5, 2005

You guys aren't going to believe this, but that guy is our games teacher.
If you know in advance which class(es) and member function(s) you need to be able to call "reflectively" you could use a factory and a static map from string to member function pointer to simulate it. This works for virtual member functions too; your compiler will generate code to do a runtime vtable lookup so it will work exactly like if you called it without the indirection.

Crazy RRRussian
Mar 5, 2010

by Fistgrrl

Mr.Radar posted:

If you know in advance which class(es) and member function(s) you need to be able to call "reflectively" you could use a factory and a static map from string to member function pointer to simulate it. This works for virtual member functions too; your compiler will generate code to do a runtime vtable lookup so it will work exactly like if you called it without the indirection.

Is there any automated way of doing this? like via some crazy macros to generate such a map?

litghost
May 26, 2004
Builder

Crazy RRRussian posted:

Is there any automated way of doing this? like via some crazy macros to generate such a map?

boost::fusion can make tuples of structures. See BOOST_FUSION_ADAPT_STRUCT. I am not sure that you can get the name of the field through, you would need to try it out.

Lexical Unit
Sep 16, 2003

Should this compile or not?
code:
#include <list>

using namespace std;

template<class T>
struct foo
{
	typedef std::list<T> list_type;
	list_type list;
};

template<class T>
bool operator<(const foo<T>& lhs, const foo<T>& rhs)
{
	return lhs.list < rhs.list; //  error: `.' cannot appear in a constant-expression
}
I'm not sure, but it seems like this shouldn't be a problem. Easily fixed of course, just rename the data member. But I'd like to understand why it doesn't work (I've tested only on gcc 4.2.1) if it truly shouldn't work in the first place. That is, that it's not just a compiler bug.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
Ahahaha. This is the most terrible thing in the world.

So, the compiler has to decide whether the '<' in "lhs . list <" starts a template-id. If the type of 'lhs' is dependent (and not a current instantiation), then it can't just look into that type. You would think that the appropriate thing to do here would be to require the 'template' keyword, which is indeed required in other, similar contexts, but no: instead the standard requires us to look up the identifier in lexical scope to see whether it names a template. In this case, it does, so just in case you're trying to say "lhs.list<T>::blah" the compiler continues to parse that as a template-id. Of course that won't work because it's syntactically malformed; however, apparently before it figures that out, gcc complains about how "rhs.list" (which it's just parsed as a non-type template argument) is not a constant expression, and then stops there.

The solution is to parenthesize lhs.list.

Lexical Unit
Sep 16, 2003

Oh duh. The fact that it was looking for a constant expression should have clued me into the issue with parsing <, especially since the compiler had no issue with the other defined operators.

Foran
Apr 19, 2008

Garry's Mod is an Art
I'm having a bit of trouble with this:

code:
void genwilderness(int x, int y)
{
    int r;
    for (int i=0;i<500;i++)
    {
       x=i;
       r = rand() % 3 + 1;
       if (r == 1)
       {
           mapchar[x][y] = 'T';
       }
       else if (r == 2)
       {
           mapchar[x][y] = ',';
       }
       else if (r ==3)
       {
           mapchar[x][y] = '.';
       }
       if(x==500){
       y++;
       }
        TCODConsole::root->setChar(x,y,mapchar[x][y]);
        TCODConsole::root->flush();
    }
}
It loops forever and will only generate wilderness on a single row. Any ideas?

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
I don't believe you that this function loops forever. I do believe that it only generates one line, though, because i goes from 0 to 499, and then you fall out of the loop and return. And I can believe that your program loops forever if you call this function in a loop, passing in a variable called 'y' and expecting it to be modified in the calling function.

I think you don't really understand local variables. Also, that store to 'y' will never, ever be executed.

rjmccall fucked around with this message at 21:52 on Jul 22, 2010

Foran
Apr 19, 2008

Garry's Mod is an Art
I can't say I do. this is my first serious project with any programming language, and I haven't taken any classes or anything on it. Thanks for the kinda-help though.

Foran fucked around with this message at 21:56 on Jul 22, 2010

MagneticWombats
Aug 19, 2004
JUMP!

Rsugar posted:

I can't say I do. this is my first serious project with any programming language, and I haven't taken any classes or anything on it. Thanks for the kinda-help though.

The y in your function is a local variable. If you do:

code:
int y = 10;
generatewilderness(4,y);
y will still be 10 at the end. The y inside your function is different from all other ys in your code.

MagneticWombats fucked around with this message at 22:28 on Jul 22, 2010

Foran
Apr 19, 2008

Garry's Mod is an Art
Thanks, that bit of info helped fix the problem.

Bandamyion
Oct 22, 2008

MagneticWombats posted:

The y in your function is a local variable. If you do:

code:
int y = 10;
generatewilderness(4,y);
y will still be 10 at the end. The y inside your function is different from all other ys in your code.

Also "x" as the input parameter get overwritten immediately, losing any info the param holds. Re-engineer your function matey.

Crazy Russian, any luck on your c++ reflection project ?

Jan
Feb 27, 2008

The disruptive powers of excessive national fecundity may have played a greater part in bursting the bonds of convention than either the power of ideas or the errors of autocracy.
I'm kind of puzzled by the typing of rectangular arrays. I've been messing around with a test program and I'm mostly looking for a confirmation as to whether I've come to the right conclusions.

code:
#include <cstring>

typedef char rowchar[3];

int main(int argc, char ** argv)
{
	char cStack[4][3] = {{'w', 'w', 'w'},
						 {'x', 'x', 'x'},
						 {'y', 'y', 'y'},
						 {'z', 'z', 0}};

	char ** cHeap = new char * [4];

	for (int i = 0; i < 4; i++)
	{
		cHeap[i] = new char[3];
	}

	for (int j = 0; j < 4; j++)
		for (int i = 0; i < 3; i++)
			cHeap[j][i] = cStack[j][i];

	char (&cStackRow)[3] = cStack[0];

	char (&cRef)[4][3] = cStack;

	rowchar * cRow = new rowchar[5];

	char * cString = (char*)cStack;
	char * cRowString = (char*)cRow;
	
	memcpy(cRowString, cString, 12);

	//char cFlip[3][4] = reinterpret_cast<char[3][4]>((char**)cStack);
	//char (&cSStack)[4][3] = (char[4][3])cString;

	char cStackLookup = cStack[2][2];

	char cStringLookup = cString[2 * 3 + 2];

	char cHeapLookup = cHeap[2][2];

	return 0;
}
The original array is sequential and I can cast it into pretty much anything, however I can't figure out a way to cast something back into the multidimensional array syntax.

If, instead of using a rectangular array, I use a char **, I can use the double [][] notation again. I've been messing around with MSVC's debugger, as well as generated assembly trying to figure out how each type is stored and looked up.

Obviously, the [][] notation is completely different in a rectangular array from an array of arrays. I understand how the array of arrays works, and the double lookup that follows. What I'm not sure about is the rectangular array.

From what I can tell, the rectangular array lookup is translated into a simple, dumb copy directly from the right position in the stack. Given this, I'm assuming the [][] notation is just syntactic sugar from the compiler for rectangular arrays, which get translated into offsets on the stack.

Since the real meaning of [] is a pointer lookup rather than a stack offset, that kind of lookup fails if I cast cStack to a char ** like this:
code:
	char ** cBad = (char**)cStack;
	char cBadLookup = cBad[2][2];
as this ends up fetching the third character of cStack and then incorrectly dereferences that as the address to read from.

Given all this, is it safe to assume that the compiler will never let me cast something back into a char[4][3] type as I'm attempting to do in the commented lines? Or is there a syntax I haven't figured out that could do that?

Mustach
Mar 2, 2003

In this long line, there's been some real strange genes. You've got 'em all, with some extras thrown in.
Remember that pointers are not arrays; they types you're casting from are distinct. Here's an illustration that's hopefully intuitive: T **pp is a pointer to an element of an array of pointers, and T (*pa)[N] is a pointer to an element of an array of arrays. pp + 1 will be sizeof(T*) bytes from pp. pa + 1 will be sizeof(T[N]) bytes from pa.

Also keep in mind that this distinction doesn't have anything to do with stack versus heap. If you wanted to dynamically allocate a 2-dimensional array, it'd be something like char (*p)[5] = new char [x][5];

Jan
Feb 27, 2008

The disruptive powers of excessive national fecundity may have played a greater part in bursting the bonds of convention than either the power of ideas or the errors of autocracy.
Ah, figures, I looked through the C++ FAQ but didn't think to look for a C FAQ for, well, C-like issues. :doh:

Thanks, that should help me figure things out.

Jan
Feb 27, 2008

The disruptive powers of excessive national fecundity may have played a greater part in bursting the bonds of convention than either the power of ideas or the errors of autocracy.
Running into an initialization problem due to the way some of my classes are setup. Here are the relevant constructors, boiled down to their basics:

code:
Track::Track(int channelCount)
: _channelCount(channelCount) // _channelCount is const
code:
FileTrack::FileTrack(const std::string& filename)
: _file(filename), Track(_file.channels())
Due to the order of initialization, the file handle isn't initialized when the base Track is constructed. Ergo, I can't provide the channel count in time for the base class.

I'm trying to do everything according to RAII and it's been working great so far, but I don't know how to fix this without fundamentally breaking that design. :(

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
If you want to maintain this exact interface, and file handles aren't movable, then you'll need to derive from a private base class which holds the handle:
class FileTrack : private FileHandlerHolder, public Track {...};

Vanadium
Jan 8, 2005

FileTrack::FileTrack(const std::string& filename)
: Track((new (&_file) WhatEverFileIs(filename))->channels())


:supaburn:

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
I feel like we can safely assume that WhatEverFileIs isn't trivially constructable and destructable. :)

Jan
Feb 27, 2008

The disruptive powers of excessive national fecundity may have played a greater part in bursting the bonds of convention than either the power of ideas or the errors of autocracy.
That's the strangest use of a placement new I've ever seen.

Private inheritance works like a charm, thanks for reminding me of its existence! :haw:

Vanadium
Jan 8, 2005

rjmccall posted:

I feel like we can safely assume that WhatEverFileIs isn't trivially constructable and destructable. :)

Does it count if we derive from it and give the new class a special constructor that does nothing?

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
The new class's constructor would still need to (implicitly) construct its base class.

I think you could make this work with something like:

code:
class FileTrack : public Track {
  union {
    void *_aligner; // or however you want to achieve this
    char _file[sizeof(WhatEverFileIs)];
  };
  bool _file_initialized;

  FileTrack(const std::string &filename)
   : Track((_file_initialized = false,
            new (&_file) WhatEverFileIs(filename),
            _file_initialized = true,
            static_cast<WhatEverFileIs*>(&_file)->channels()))
  try {} catch (...) { if (_file_initialized) static_cast<WhatEverFileIs*>(&_file)->~WhatEverFileIs(); }
  ~FileTrack() { static_cast<WhatEverFileIs*>(&_file)->~WhatEverFileIs(); }
};

Bandamyion
Oct 22, 2008

Vanadium posted:

FileTrack::FileTrack(const std::string& filename)
: Track((new (&_file) WhatEverFileIs(filename))->channels())


:supaburn:

That is worth 8 hrs man time ripping out and re-testing on it's own. Do it for the good of the community :)

Magicmat
Aug 14, 2000

I've got the worst fucking attorneys
I'm trying to tweak the way a Qt widget works. (Long story short: I'm trying to add validation to the edit mode of a QListView.) After looking over the (LGPL'ed) source, I've come to the conclusion I'm going to have to alter how a particular function works. Problem is, this function isn't virtual. I could just wrap the function in a sub-class function, but the super-class function is called from a few different places inside the super-class, so that's no good.

What's the best way to do this? If I override this non-virtual function in the sub-class, and promise never to polymorphisize it, will the function calls in the super-class still hit on the non-overridden super-class version of the function?

I know that's not the best idea, even if it does work, but the only other thing I can think of is to copy+paste the whole drat 4,000+ line source for the QListView (well, technically QAbstractItemView) widget, add the keyword "virtual" to the function, and rename the class. Aside from the PITA aspect, I'll then lose out on future updates to the class put out by Trolltech/Nokia -- essentially locking me in to the current release of Qt.

OddObserver
Apr 3, 2009
If you want custom validation in a Qt MVC widget, you can create and set a delegate that overrides the createEditor method; see http://doc.qt.nokia.com/latest/model-view-delegate.html#providing-an-editor

And no, you can't override a non-virtual and have the superclass call the child class version. It's impossible.

Jan
Feb 27, 2008

The disruptive powers of excessive national fecundity may have played a greater part in bursting the bonds of convention than either the power of ideas or the errors of autocracy.

OddObserver posted:

And no, you can't override a non-virtual and have the superclass call the child class version. It's impossible.

Er...

code:
class A
{
public:
	void foo()
	{
		std::cout << "A::foo" << std::endl;
	}
};

class B : public A
{
public:
	void foo()
	{
		A::foo();
		std::cout << "B::foo" << std::endl;
	}
};

int main(int argc, char ** argv)
{
	B bar;

	bar.foo();

	return 0;
}
Outputs:
A::foo
B::foo

OddObserver
Apr 3, 2009
That's not the superclass calling the child version. You're calling the child version, which in turn calls the parent version.

I was sort of wrong considering the whole:
class ChildClass: public Foo<ChildClass> pattern, though, but that doesn't apply here anyway (I was thinking of a -fixed- base)

Jan
Feb 27, 2008

The disruptive powers of excessive national fecundity may have played a greater part in bursting the bonds of convention than either the power of ideas or the errors of autocracy.
Oh, duh. I was just waking up and hadn't taken my morning coffee, I completely mixed up the terminology. :downs:

Yeah, nevermind. I can't see how you could do that short of using ugly memory replacement hacks.

Daviclond
May 20, 2006

Bad post sighted! Firing.
I have to output a bunch of data in a format that is readable by an analysis program. After some trial and error, I've figured out that the program parses data by using field width rather than a delimiter (it reads a value every ten characters) but I'm having trouble outputting in this format.

The simplest way to do it, I figure, is to output each datum with seven digits before the decimal place and one figure after (I only need 1 d.p. precision) plus a space to delimit data elements, thus giving a total of 10 characters. I'm doing the work in MATLAB and using the 'dlmwrite' function which allows modification of the precision attribute. From the dlmwrite help file:

code:
"'precision' =>  Numeric precision to use in writing data to the
                        file, as significant digits or a C-style format
                        string, starting with '%', such as '%10.5f'.  Note
                        that this uses the operating system standard
                        library to truncate the number."
I thought using '%7.1f' would give what I need but apparently not, it does not force seven digits to precede the decimal place. Having googled "C-style format string" and looked at some resources I'm not really any the wiser on what I should alter the format to, I have very basic programming knowledge and don't fully understand much of the terminology. Any suggestions? I can give samples of what the output should look like and what I'm getting or more details if I haven't explained fully :)

Jan
Feb 27, 2008

The disruptive powers of excessive national fecundity may have played a greater part in bursting the bonds of convention than either the power of ideas or the errors of autocracy.

Daviclond posted:

:words:

Well this isn't really a MATLAB thread but I think the problem isn't your formatting string but rather that dlmwrite doesn't actually use string formatting. Try fprintf instead.

Daviclond
May 20, 2006

Bad post sighted! Firing.

Jan posted:

Well this isn't really a MATLAB thread but I think the problem isn't your formatting string but rather that dlmwrite doesn't actually use string formatting. Try fprintf instead.

That function uses the same formatting style, but happens to mention you can prefix the field value with a space or a zero to pad it with spaces or zeroes. Putting '% 9.1f' instead of '%9.1f' (apparently the field length refers to the entire number, so I wanted a 9 not a 7) into the dlmwrite function gives me the required output, thanks :)

Jan
Feb 27, 2008

The disruptive powers of excessive national fecundity may have played a greater part in bursting the bonds of convention than either the power of ideas or the errors of autocracy.
(I know this thread isn't about .NET, it's just context for what is really just a C++ question)

C++/CLI allows mixing native types with managed types, so long as they are pointers or references. Now I have a class which wraps a native type, with a 1:1 composition relationship. If it wasn't for the C++/CLI mixing restriction, I'd just make it a member variable, but since it has to be a reference or pointer, I'm faced with 2 alternatives:

A const pointer:
code:
ref class ManagedPtr
{
	NativeType* const _native;

	ManagedRef() : _native(new NativeType())
	{
	}

	~ManagedRef()
	{
		delete _native;
	}

	const NativeType& GetInnerType() const
	{
		return *_native;
	}
};
A "fake" reference:
code:
ref class ManagedRef
{
	NativeType& _native;

	ManagedRef() : _native(*(new NativeType()))
	{
	}

	~ManagedRef()
	{
		delete &_native;
	}

	const NativeType& GetInnerType() const
	{
		return _native;
	}
};
Is there any reason not to go with the fake reference? I know references are essentially supposed to alias existing objects, but using this syntax is really aliasing a new object that doesn't exist anywhere else, which is not really the intent of references. I can't see any technical reason why this wouldn't work, it seems mostly a matter of preference.

handsome only face
Apr 22, 2010

Cockroach went out of the room in anger. And roach's go to empty room...

Cockroache's Anarchist


beep boop

handsome only face fucked around with this message at 22:40 on Jul 27, 2010

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Jan posted:

Is there any reason not to go with the fake reference? I know references are essentially supposed to alias existing objects, but using this syntax is really aliasing a new object that doesn't exist anywhere else, which is not really the intent of references.

There is absolutely nothing wrong with binding a reference to a heap object that the reference "owns". You do have to watch out for the pointer being null, but in this case (assuming you're using exceptions) that should not be possible.

awesmoe
Nov 30, 2005

Pillbug

"Avenging Dentist" in March posted:

Timothy Madden is desperately clinging to a language feature that even he acknowledges isn't actually that useful.
Update: He's doing it again. That dude fucken loves export.

Adbot
ADBOT LOVES YOU

Ciaphas
Nov 20, 2005

> BEWARE, COWARD :ovr:


Are there any hard-and-fast rules I can use for when STL container iterators can become invalidated/shouldn't be used anymore? Things like inserting/erasing while iterating, resizing, whatever. It seems like the rules change every goddamn time I have to debug something, and my google-fu is proving weak except for some PDF that has few real examples.

Running into a goofy bug with a find() call on a map causing a segfault and it's really aggravating, I'm kind of flailing hoping I have a screwed up iterator somewhere at this point :smith:

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