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
Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

Brecht posted:

But, frankly, I don't know why this compiles. My understanding of dynamic_cast is that it works up and down the inheritance hierarchy, but not sideways. Is that wrong? Is it really able to do arbitrary casting regardless of inheritance ancestry?
The relevant part of the standard (C++03 §5.2.7.8):

quote:

Otherwise, if v points (refers) to a public base class sub-object of the most derived object, and the type of the most derived object has a base class, of type T, that is unambiguous and public, the result is a pointer (an lvalue referring) to the T sub-object of the most derived object.
The fact that Fundamental and IStuff are unrelated types doesn't matter, only that the most derived type (C or D) is derived unambiguously and publicly from both of them.

Adbot
ADBOT LOVES YOU

Brecht
Nov 7, 2009

Plorkyeran posted:

(C++03 §5.2.7.8)
I have learned something today.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem

roomforthetuna posted:

Which is to say, I think
\<[^>]*[^[:print:]][^>]*\>
would work if all you need to do is detect that there is a non-printable in a tag.

Sorry, I had to catch some sleep, but yeah this is basically what I was getting at.

In my breakdown of the problem, parts 2 and 4 were identical - and I broke down the regex to try in show that in your solution, you had two different things for those parts.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
My problem is that I need to pass the type information dynamically. In your examples you are still giving it the type at compile time. Let me show you what works so long as I am referring to the object by it's final type:
code:
Fundamental* ThingThatHasContainer::As(const std::type_info &type)
{
	for(container_type::iterator i = container->begin(); i != container->end(); ++i)
	{
		Fundamental* fund = *i;

		if(typeid(*fund) == type)
		{
			return fund;
		}

	}

	// Made it here?  return nothing
	return NULL;
}
say container_type is list<Fundamental*>, and it contains:
code:
class A : public Fundamental
class B : public Fundamental
class C : public IStuff, public Fundamental
If I call As(typeid(A)), I'll get back my A object fine. If I call As(typeid(C)), I'll get back my C object fine. But if I call As(typeid(IStuff)) then I get NULL.

As far as I can tell, I cannot use dynamic_cast on there with a dynamic type_info argument. Say, I could do dynamic_cast<IStuff> and be fine, but again, as a template argument that is getting sorted out somewhat at compile time. I want to be able to call dynamic_cast<a type_info variable here>, or perhaps more relevant would be dynamic_cast(type_info, pointer).

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
For those specific examples, it's trivial: just template the function (and optionally get a better return type in the process):
code:
template<class T>
T* ThingThatHasContainer::As()
{
	for(container_type::iterator i = container->begin(); i != container->end(); ++i)
	{
		if (T *item = dynamic_cast<T*>(*i))
		{
			return item;
		}
	}

	// Made it here?  return nothing
	return NULL;
}

// Called as
thing->As<C>();
// etc.
Alternatively, if templating As isn't an option for whatever reason:
code:
template<class T>
static bool is_of_type(Fundamental *item)
{
	return dynamic_cast<T*>(item) != NULL;
}

// Well really you should probably use std::function<bool, Fundamental*>
Fundamental* ThingThatHasContainer::As(bool (*predicate)(Fundamental*))
{
	container_type::iterator i = std::find_if(container->begin(), container->end(), predicate);
	if (i != container->end)
	{
		return *i;
	}
	return NULL;
}

// Called as
thing->As(is_of_type<IShape>);

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
You could never do a proper dynamic_cast to a dynamically-specified type — the result would necessarily be dependently typed, and C++ doesn't do runtime dependent typing.

Three more alternatives on top of what Plorkyeran suggested:

1. Add a virtual method whose purpose is to dynamic_cast down to a specific type, and pass a member-function-pointer for that method around instead of a type_info&. Obviously, the standard implementation would return null, and the target class would override that to stop returning null. This has the advantage of being amazingly faster than an actual dynamic_cast, with the disadvantage of bloating your vtables and requiring a new method for every target type.

2. Shadow the type system with some sort of "this is my dynamic type" field. Again, massively faster than dynamic_cast because casts are just equality or range tests, but this time it requires bloating the object instead of the vtable. Generally slightly faster than #1 (test+branch instead of call+test+branch), but doesn't necessarily play well with multiple inheritance.

3. Write non-portable code. dynamic_cast is implemented with a runtime function; you can always call that function yourself. Of course, it's a different function on different platforms, but for almost every UNIX-y platform (including MacOS/iOS) it's a function called __dynamic_cast documented in the Itanium ABI. I don't know know off-hand what the function is in MSVC.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
Anything that requires I resolve it at compile-time won't work; ultimately this code is serving like a library or runtime for another language--in this case, Python. Fun fact: Boost's Python bindings seem to handle type_info fine, so I can actually call that As() method in Python.

Ultimately I can skirt past this problem because it came up while writing some intermediate code, and I think in the final implementation I won't even do those kind of lookups. However, I was generally just frustrated to find that C++ didn't have a direct ability to do this. I have been getting used to generics in other languages so I think they spoiled me.

Paniolo
Oct 9, 2007

Heads will roll.
That ABI spec is one incredibly informative link - thanks for that. Do similar documents exist for x86 and x64?

By the way Rocko the problem you're describing is the basis for COM's QueryInterface system.

Paniolo fucked around with this message at 08:33 on Sep 6, 2011

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!

Paniolo posted:

By the way Rocko the problem you're describing is the basis for COM's QueryInterface system.
Oh man you're telling me COM makes some kind of sense?!

Sephiroth_IRA
Mar 31, 2010
From the book on Inline Member Functions:

"Inline member functions are compiled differently than other functions, in the executable code, inline functions aren't "called" in the conventional sense. In a process known as inline expansion, the compiler replaces the call to an inline function with the code to the function itself. This means that the overhead needed for a conventional function call isn't necessary for an inline function and can result in improved performance*"

"*Because inline functions cause code to increase in size, they can decrease performance on systems that use paging.*

So, I'm going to assume that using this technique on a Windows machine is a no-no? Do other operating systems use paging? What is the modern (My book is from 2004) take on this?

edit: I'm going to take a partial guess and assume that concerns over performance isn't something to worry over so much these days but I will still like to create high-performance code in the future.

TasteMyHouse
Dec 21, 2006

Orange_Lazarus posted:

From the book on Inline Member Functions:

"Inline member functions are compiled differently than other functions, in the executable code, inline functions aren't "called" in the conventional sense. In a process known as inline expansion, the compiler replaces the call to an inline function with the code to the function itself. This means that the overhead needed for a conventional function call isn't necessary for an inline function and can result in improved performance*"

"*Because inline functions cause code to increase in size, they can decrease performance on systems that use paging.*

So, I'm going to assume that using this technique on a Windows machine is a no-no? Do other operating systems use paging? What is the modern (My book is from 2004) take on this?

edit: I'm going to take a partial guess and assume that concerns over performance isn't something to worry over so much these days but I will still like to create high-performance code in the future.

read this, especially 9.3.

Pretty much every OS (e: that you're likely to run into) uses paging. The rule of thumb with inline functions is to use them only when the function is extremely short.

TasteMyHouse fucked around with this message at 15:01 on Sep 6, 2011

tractor fanatic
Sep 9, 2005

Pillbug
Inline is just a suggestion to the compiler anyways, it doesn't have to actually inline it.

raminasi
Jan 25, 2005

a last drink with no ice
The compiler is also allowed to inline things that aren't declared as such if link-time inlining is enabled. What usually ends up happening is that whether a function is declared inline or not has far more to do with where it's allowed to be defined (because of template stuff) than any kind of performance concern.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

Rocko Bonaparte posted:

Anything that requires I resolve it at compile-time won't work; ultimately this code is serving like a library or runtime for another language--in this case, Python. Fun fact: Boost's Python bindings seem to handle type_info fine, so I can actually call that As() method in Python.
With boost.python the types which will be exposed to python must be known at compile time (and explicitly exposed). You can trivially construct a mapping from type_info to predicate function for all of the types you're exposing to python at the same time as you're registering them with boost.python.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!

Plorkyeran posted:

With boost.python the types which will be exposed to python must be known at compile time (and explicitly exposed). You can trivially construct a mapping from type_info to predicate function for all of the types you're exposing to python at the same time as you're registering them with boost.python.
That should work when exposing the C++ code to Python. The trick--going back to my example here--is that I am subclassing Fundamental in Python too. As far as my basic experiments went, it appeared to handle that okay. However, I had to override that As() method to accept a python type information handle instead.

more falafel please
Feb 26, 2005

forums poster

Orange_Lazarus posted:

From the book on Inline Member Functions:

"Inline member functions are compiled differently than other functions, in the executable code, inline functions aren't "called" in the conventional sense. In a process known as inline expansion, the compiler replaces the call to an inline function with the code to the function itself. This means that the overhead needed for a conventional function call isn't necessary for an inline function and can result in improved performance*"

"*Because inline functions cause code to increase in size, they can decrease performance on systems that use paging.*

So, I'm going to assume that using this technique on a Windows machine is a no-no? Do other operating systems use paging? What is the modern (My book is from 2004) take on this?

edit: I'm going to take a partial guess and assume that concerns over performance isn't something to worry over so much these days but I will still like to create high-performance code in the future.

The relevant section of the C++ FAQ Lite is:

quote:

There are no simple answers: You have to play with it to see what is best. Do not settle for simplistic answers like, "Never use inline functions" or "Always use inline functions" or "Use inline functions if and only if the function is less than N lines of code." These one-size-fits-all rules may be easy to write down, but they will produce sub-optimal results.

There's no easy way to know without profiling it. Generally, trust the compiler, then, when you know you have a problem with certain functions being inlined or certain functions not being inlined (because you profiled it), make a decision one way or another.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Paniolo posted:

That ABI spec is one incredibly informative link - thanks for that. Do similar documents exist for x86 and x64?

Despite its name, the Itanium C++ ABI is actually cross-platform; it's basically a generic set of rules for implementing the runtime features of C++ in terms of whatever the C rules are for a platform. The decision of whether to use it is more about the platform vendor than the underlying architecture. Microsoft had their own ABI before the Itanium ABI was written, so Win32 uses something substantially different; Win64 is closer but still definitely its own thing. But, for example, the MacOS, Linux, and BSD x86/x86-64 platforms all use the Itanium ABI.

Sephiroth_IRA
Mar 31, 2010
Thanks for the replies, all were very helpful. I'm going to read the FAQ in it's entirety eventually. Anyways onto my next problem:

I'm more than half way through the book and I have to admit my current understanding of a lot of the practice code is muddled. Don't laugh but here's what I think is going on with the code I'm currently working with.

code:
//This program demonstrates a class with a constructor
//that dynamically allocates memory.

#include <iostream>
#include <cstring>
using namespace std;

// InventoryItem class declaration.

class InventoryItem
{
      private:
              char *description;
              int units;
      public:
             InventoryItem()
             { description = new char [51]; }  //New syntax is NEW to me... I had to read up on this in Wikipedia, nothing in the current section of the book.

      void setDescription(char *d) //Receives "Wrench" from the function call.  Assigns "Wrench" to the character pointer *d  This was passed by reference?
           {strcpy(description, d); } //Copies "Wrench" from d into description (an array of 51 chars.)

      void setUnits(int u) //initializes an integer u which receives the value 20 from the setUnits function call.
           { units = u; } //Assigns the value 20 from int u to units.

      char *getDescription() //passes descriptin by reference to the function call.
           { return description; } //Returns description to *getDescription

      int getUnits()  //Returns the value from units (or just units) to the function call.
           {  return units;  } // Returns units getUnits()
           
};

//********************************
//Main.
//*********************************

int main()
{
    InventoryItem stock;  //creates an instance of the InventoryItem class (A variable named stock)
    
    stock.setDescription("Wrench"); //Passes the string wrench to setDescription (Function call)
    stock.setUnits(20); //Passes the value 20 to the setUnits function. (Function call)
    cout << "Item Description: " << stock.getDescription() << endl; //Calls the getDescription member function.
    cout << "Units on hand: " << stock.getUnits() << endl; //Calls the getUnits member function.
    return 0;
}
I have to admit I've been skipping the creative practice which I'm sure would help a lot but the assignments are so boring and by the time I've glanced over the instructions my eyes have glazed over and I'm hungry for the next chapter.

I keep telling myself that once I've digested the book, I would move onto creating my own code and learning SDL through trial and error. I'm not sure this is the best strategy anymore. Any suggestions?

Sephiroth_IRA fucked around with this message at 02:54 on Sep 7, 2011

TasteMyHouse
Dec 21, 2006
There's a little bit of confusion of terms here. "Pass-by-reference" can indeed refer to passing a pointer to some data around, but since there are actually special types in C++ called "references" it's probably best to just talk of passing pointers around.

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!

Orange_Lazarus posted:

code:
//This program demonstrates a class with a constructor
//that dynamically allocates memory.
Two comments on your code there - one, generally for every time you use a 'new' you should have a corresponding 'delete' (not necessarily one distinct call for each, for example you might 'new' three sorts of objects, putting them into a list, and then 'delete' everything in the list when it's destroyed, so there would only be one instance of 'delete', but a delete should be called for every time new is called.)

That code didn't have a 'delete' in it at all, which is not good.

And two, your comments say "creates an instance of the InventoryItem class" but don't acknowledge that this instance is deleted when it goes out of scope because it's a local variable. I don't know if that's something that you understand or not, but if you're going to overcomment something, remarking on the creation of a thing without mentioning its deletion is a lot like the new/delete divide. :)

In that specific code, since the char array is new'd in the class constructor, it should probably be equally deleted in the destructor. Of which there isn't one. Though really since it's supposed to be a C++ example, it would make more sense for that string to be stored in a std::string rather than a char array, in which case you would need neither to explicitly allocate nor deallocate it. Hopefully the very next thing in the book went on to say "but that was horrible and we should have deleted it, here's how."

Your book is teaching you the same horrible "C but with classes" that I learned, and I don't recommend learning that way. Learning C first then proper C++ with standard templates and everything afterwards makes a lot more sense - or skipping C and then going back to learn about that lower-level stuff later might make even more sense. But spludging it together is horrible and took me years to get over.

Sephiroth_IRA
Mar 31, 2010
Oh god. :( That's depressing. Maybe I should just start with a new book. Yeah, after about 750 pages I'm just now learning about classes (with about 3-4 hundred pages left) I've noticed that other books start on classes/oop way earlier.

Unless I grab a new text my strategy now is to focus on the new poo poo during my first 2 hours of work (AKA "Chill Time") and then work on the practice problems / creative sections (Starting all the way back at chapter 1) an hour or more each night.

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!

roomforthetuna posted:

Two comments on your code there - one, generally for every time you use a 'new' you should have a corresponding 'delete'
Or better yet, use auto_ptr/shared_ptr so the app doesn't leak memory every time you forget a delete or miss an exception.

RAII is probably the single most useful thing about C++ and it's best to understand it early.

OneEightHundred fucked around with this message at 04:20 on Sep 7, 2011

brosmike
Jun 26, 2009

OneEightHundred posted:

Or better yet, use auto_ptr/shared_ptr so the app doesn't leak memory every time you forget a delete or miss an exception.

RAII is probably the single most useful thing about C++ and it's best to understand it early.

RAII is great, but auto_ptr is deprecated and broken - you should typically be using unique_ptr instead.

Coffee Mugshot
Jun 26, 2010

by Lowtax

brosmike posted:

RAII is great, but auto_ptr is deprecated and broken - you should typically be using unique_ptr instead.

This is useful, I didn't know about unique_ptr before. Speaking of, does anyone have a good reference for learning about the new things in C++0x. Other than go learn boost, I guess?

brosmike
Jun 26, 2009

Rainbow Pony Deluxe posted:

This is useful, I didn't know about unique_ptr before. Speaking of, does anyone have a good reference for learning about the new things in C++0x. Other than go learn boost, I guess?

If you want an overview of what new features exist, the Wikipedia article is a good starting point.

One of the lead Standard Template Library developers at Microsoft, Stephan T. Lavarej, has a very well-done video series on the STL that covers several (though not all) of the more useful new features. All of the videos are good, but if the new C++0x stuff is what you're most interested in you might want to focus on the smart pointer, rvalue, and algorithm/functor videos. He occasionally delves into implementation details that are specific to Microsoft's STL implementation, but most of the information in the introductory series is fairly platform agnostic (there is also an "advanced" series that is much more MSVC specific).

I don't know of any truly great centralized resources on all of the new features, unfortunately - the final spec was only approved less than a month ago. In particular, I don't think there are any good books that go through the new features yet (and as I recall, Stephan commented the same on a few of those videos - he's probably a pretty definitive source on the topic).

Ciaphas
Nov 20, 2005

> BEWARE, COWARD :ovr:


Why in the name of god does Sun Studio let this code compile?

code:
#include <boost/shared_ptr.hpp>

using namespace boost;

class A
{
};

int main()
{
   shared_ptr<A> a;
   a.reset(new A);

   delete a; // >:T
}
It segfaults, of course :negative:

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
My dumb guess would be that it's related to that boost::shared_ptr has an actual operator bool() (rather than operator unspecified-bool-type()) when compiling with suncc and the compiler is doing some bogus implicit conversions. Does it still segfault if you comment out the reset?

Ciaphas
Nov 20, 2005

> BEWARE, COWARD :ovr:


Plorkyeran posted:

My dumb guess would be that it's related to that boost::shared_ptr has an actual operator bool() (rather than operator unspecified-bool-type()) when compiling with suncc and the compiler is doing some bogus implicit conversions. Does it still segfault if you comment out the reset?

Ahh, good catch, no it doesn't.

We're trying to convert a particularly nasty piece of our code from using raw pointers to smart pointers, because we keep loving up and leaking/double deleting.

And by "we're trying to convert" I mean "I'm trying to convert" because I'm a stupid punishment glutton and oh god this sucks :(

Hughlander
May 11, 2005

C++ macro trickery... I made some logging macros a long time ago that look like:
code:
#if defined(DEBUG)
	#define BEGIN_TRACE_LEVEL(var, lvl) \
		if(IsTraceEnabled(#var, lvl))\
			{TStringBuffer<512> _szFormattedMsg, _szTempMsg; SNPrintF(_szFormattedMsg.Str(), _szFormattedMsg.Capacity(), "[%s %s:%d] ", #var, __FUNCTION__, __LINE__);

	#define END_TRACE_LEVEL(...) \
		printf(_szTempMsg.Str(), _szTempMsg.Capacity() - _szFormattedMsg.StrLen(), ## __VA_ARGS__ ); _szFormattedMsg.Concatenate(_szTempMsg.Str()); ConsolePrint(_szFormattedMsg.Str()); }
#else
	#define BEGIN_TRACE_LEVEL(var, lvl) (void)0;
	#define END_TRACE_LEVEL( ... ) (void)0;
#endif
The idea being that you could combine them into a single macro like
#define SOMEDEBUG( ... ) BEGIN_TRACE_LEVEL(SomeDebug, 3) END_TRACE_LEVEL( __VA_ARGS__ )

and then sprinkle your code with SOMEDEBUG("This happened"); and only if the SomeDebug variable was >= 3 would it print.

The intention was though that people could expand on it and do things like:
code:
	BEGIN_SOME_TRACE()
		SomeType* pSomething = Somethingelse; 
	END_SOME_TRACE( "%s: %s did something to some %s", __FUNCTION__, pSomething->something());
The only problem is that now that people are using it, in debug they're in their own scope, in non debug any code in the block is still being executed. And being defined so if you place that same macro twice in one comment pSomething is being redefined.

Is there a way to make a macro that is basically #if 0 and #endif? IE: From one macro to the next nothing is compiled / in scope?

EDIT:: I posted the question on StackOverflow as well and while I was doing so thought of one way around it...

code:
#else
	#define BEGIN_TRACE_LEVEL(var, lvl) if(0){
	#define END_TRACE_LEVEL( ... ) }
#endif
Abuse the hell out of the optimizing compiler...

Hughlander fucked around with this message at 15:43 on Sep 10, 2011

MrMoo
Sep 14, 2000

I saw that question, it's pretty bad to bypass braces and use macros, your IDE is going to go ape.

I've gone with the following for long trace sections:
code:
if (PGM_UNLIKELY(pgm_log_mask & PGM_LOG_ROLE_NETWORK))
{
  char s[INET6_ADDRSTRLEN];
  pgm_sockaddr_ntop ((struct sockaddr*)&recv_addr, s, sizeof(s));
  pgm_debug ("bind succeeded on recv_gsr[0] interface %s", s);
}
For short one liners:
code:
pgm_trace (PGM_LOG_ROLE_NETWORK,_("Binding send socket to interface index %u scope %u"),
           send_req->ir_interface,
           send_req->ir_scope_id);
Using macros for ISO VARARGS, GNU VARARGS, and failing back to functions for weaker compiler suites.

http://code.google.com/p/openpgm/source/browse/trunk/openpgm/pgm/include/impl/messages.h

The branch hinting works incredibly well here, the mask check is cheap and the code will be moved out of the way so the optimum case runs efficiently.

MrMoo fucked around with this message at 17:21 on Sep 10, 2011

MachinTrucChose
Jun 25, 2009
Any Qt Creator users here?

Is there any way to have the autocomplete show the function/attribute's documentation like Visual Studio and Eclipse do? And ideally also the argument's documentation? I googled and googled and I can't find anything about it. Are there any plugins that add this, even if they're commercial? VS has spoiled me rotten, I can't stand having to alt-tab to documentation (or looking it up for that matter) anymore.

Primitive Qt Creator autocomplete:


Informative VS autocomplete (notice how I not only get the function's documentation, but also its signature):

Paniolo
Oct 9, 2007

Heads will roll.

MachinTrucChose posted:

Any Qt Creator users here?

Is there any way to have the autocomplete show the function/attribute's documentation like Visual Studio and Eclipse do? And ideally also the argument's documentation? I googled and googled and I can't find anything about it. Are there any plugins that add this, even if they're commercial? VS has spoiled me rotten, I can't stand having to alt-tab to documentation (or looking it up for that matter) anymore.

Primitive Qt Creator autocomplete:


Informative VS autocomplete (notice how I not only get the function's documentation, but also its signature):


Well you're comparing a C++ IDE to a C# IDE in those screenshots. Intellisense for Visual C++ is a lot closer to the qt creator screenshot.

Hughlander
May 11, 2005

MrMoo posted:

I saw that question, it's pretty bad to bypass braces and use macros, your IDE is going to go ape.

DevStudio 2008 with Visual Assist handles it well actually. Much better than the old style I replaced it with.

quote:

The branch hinting works incredibly well here, the mask check is cheap and the code will be moved out of the way so the optimum case runs efficiently.

Not all that well on the PS3 unfortunately. This code base is probably dead when this project ships so I'm just going to fix it for now and not import it into the next project. It was a good experiment but too many issues.

Jort
Jan 10, 2007
I'm writing a program dealing with matrices. I have to create structs that hold the values inside the matrices and the maximum sum across the matrix's row. Then, I have to write functions to multiply 2 matrices and compute this maximum value.

I've gotten all the code figured out, except for one small problem. The functions to calculate the maximum sum across a row must be void functions. The paramater is a pointer directing the function to where the values inside of the corresponding matrix begins. My function populates the matrix correctly and stores this value as matrix1.maxRow (or whatever the name of the matrix is). If I print matrix1.maxRow inside of the function, it is correct. However, when I call this function inside my main() function and then try to print matrix1.maxRow, it doesn't output the correct value.

I know the function works correctly, because if I change it from a void function to a double, I can set a variable equal to the function when I call it, and print this. However, there must be some way to achieve the same goal using a void function. Can anyone point me in the right direction?


edit - Does the fact that this setMaxRow function must be of the void type mean that the only way to have this print correctly is to make this printing part of the function itself? That's the only solution I've been able to come up with.

Jort fucked around with this message at 19:47 on Sep 12, 2011

TasteMyHouse
Dec 21, 2006
It sounds like you're making a copy of the matrix rather than actually passing it by pointer. Can you post the actual signatures of the functions you're using?

Jort
Jan 10, 2007
code:

//matrix44 is a 4x4 matrix, m44 is pointing to the location of the matrix I want to calculate this value for
void setMaxRow ( matrix44 * m44)  
{
matrix44 matrix1 = *m44
// run the loop to calculate this value, storing it in matrix1.maxRow
}

Is that what you meant?

nielsm
Jun 1, 2009



Jort posted:

code:

//matrix44 is a 4x4 matrix, m44 is pointing to the location of the matrix I want to calculate this value for
void setMaxRow ( matrix44 * m44)  
{
matrix44 matrix1 = *m44
// run the loop to calculate this value, storing it in matrix1.maxRow
}

Is that what you meant?

This line:
matrix44 matrix1 = *m44;
allocates a new matrix44 object with auto-storage and copies the matrix pointed to by the function argument into it. If you make any changes to the new matrix1 object created here they won't be reflected in the one passed in, because they are distinct objects, and the new one only exists inside the function.

TasteMyHouse
Dec 21, 2006
if you want something that has the same convenience factor as that (i.e. you don't need to keep using * to get at the matrix), you can use a reference:

code:
void setMaxRow ( matrix44 * m44)  
{
matrix44& matrix1 = *m44
// do stuff
}
References are variables that act as "aliases" for other variables -- like "hard links" in Unix.

In fact, if you have the ability to change the function signature, it'd be easier to just pass the matrix by reference (though opinions differ on whether this is actually good practice):
code:
void setMaxRow ( matrix44& m44)  
{
// do stuff with m44 directly
}

Jort
Jan 10, 2007

TasteMyHouse posted:

if you want something that has the same convenience factor as that (i.e. you don't need to keep using * to get at the matrix), you can use a reference:

code:
void setMaxRow ( matrix44 * m44)  
{
matrix44& matrix1 = *m44
// do stuff
}


This was exactly what I was trying to do. Thanks!

Adbot
ADBOT LOVES YOU

Toady
Jan 12, 2009

pseudorandom name posted:

IRC is a relatively unpopular and poorly specified protocol, and to my knowledge, nobody has made an IRC library. libpurple is probably the closest thing to an IRC library, but it comes at IRC from an instant messaging perspective, and has to contort IRC to fit that worldview.

libircclient is a simple IRC library for C based on function callbacks. The other libraries I'm aware of are usually for languages other than C or C++, like ChatCore.

IRC and related protocols are so poorly specified that the "official" CTCP document isn't even adhered to by servers and clients (e.g., nobody sends more than one CTCP message per line). Client authors have to find these things out on their own because documentation of what's in conventional use takes more effort than it should to gather.

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