Skip to main content
gamedev.net
🔒 Locked

Casting and iterators.

Started by tifkagh Feb 23, 2003 at 8:50 AM 13 replies 900+ views
Original Post
tifkagh
tifkagh
I''ve written the following member with the intention of ''casting'' a vector of type mbsTileNode* to a vector of type mbsNode* and then calling the ''true'' setup function. However, my compiler vomits, and I mean vomits, at this. I was surprised by this as mbsNode is the base class of mbsTileNode so all I am rquesting the function to do is straightforward upcast.
void mbsNormalNode::Setup(vector& vnNewNodes, vector& iNewWeights, int& iNewThreshold){
  vector vnBaseNodes;

  copy(vnNewNodes.begin(), vnNewNodes.end(), back_inserter(vnBaseNodes.begin()));
  Setup(vnBaseNodes, iNewWeights, iNewThreshold);

}
 
What is the correct way to "cast" this vector. Will I have to use a normal loop to copy from my existing vector to the vector of base objects. If so, doesn''t this defeat the purpose of generic programming?
civguy
civguy
but pass by reference

[edited by - civguy on February 23, 2003 10:14:26 AM]
tifkagh
tifkagh
I tried

vector vnBaseNodes(vnNewNodes.begin(), vnNewNodes.end());

and the compiler, gcc, came back with:

/usr/include/c++/3.2/bits/stl_algobase.h:241: cannot convert mbsTileNode*' to mbsNode*' in assignment

Also, I'm a bit wary of using the template approach as this seems to underming C++ type safety.

[edited by - tifkagh on February 23, 2003 4:28:26 PM]
Zipster
Zipster
Templates actually better enforce type-safety. This is just a bad time to use them.

Try what civguy said and pass by reference:

vector vnBaseNodes(vnNewNodes);


If all else fails, fall back on a loop.
civguy
civguy
Actually what I meant was this:

  
template <class C>
void Setup(C& baseNodes, [...]) { [...] }
// ^

Making an extra copy of the vector can be expensive. I''d prefer using more templates. Unfortunately it affects the compile times quite a lot
Qw3r7yU10p!
Qw3r7yU10p!
To convert from one pointer type to another it needs to be able to see that they are related by inheritance. Include the correct headers.
Qw3r7yU10p!
Qw3r7yU10p!
sorry AP, I don''t know who you are or the quality of what you normally say, but your terminology is wrong, back to front and made up.

downcast - cast from a base class to a derived class
upgrade - improve with new technology
Ready4Dis
Ready4Dis
You can try a void *

mbsTileNode *tmp1;
mbsNode *tmp2;
tmp2 = (void*)tmp1;

This way, it CAN convert tmp1 to a void*, and tmp2 can be assigned a void*... or at least in theory . I''ve done what you''re saying, and it works fine for my code, in MSVC++ 6.0 though. It does however, give me a warning that there is no conversion for going from the base class to the new class, but it''s just a warning, and still works properly. I don''t see why you wouldn''t be able to directly cast the way you''re trying to though, isn''t that the point of inheriting, so you can treat all objects similarly, without needing to know the specific type?
Shannon Barber
Shannon Barber
quote:
Original post by tifkagh
What is the correct way to "cast" this vector. Will I have to use a normal loop to copy from my existing vector to the vector of base objects. If so, doesn't this defeat the purpose of generic programming?


As you may have expected, the correct thing to do is not to cast the vector, and generally you should never cast an iterator (the only exception is casting to or from const to non-const iterators).

The code you posted is not generic. Using a for-loop does not defeat generic programming (it does grind against functional programming).

Rewrite the orginal Setup function (that has the loop in it), to take iterators as template parameters. This will make it a generic function.


    
template<typename NodeIt, typename WeightIt>
int Setup(NodeIt begin, NodeIt end, WeightIt weight, int threshold)
{
for(; begin!=end; ++begin, ++weight)
{
//This will access the node

(*begin)-> //use *weight, do something with threshold

}
return threshold;
}


Then you'd use it like so:

assert(newnodes.size() == weights.size());
new_threshold = Setup(newnodes.begin(), newnodes.end(), weights.begin(), threshold);


If threshold is a result, return it. If it's an input parameter, pass it by value.

[edited by - Magmai Kai Holmlor on February 24, 2003 12:39:37 PM]
The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
civguy
civguy
quote:
Original post by tifkagh
Also, I''m a bit wary of using the template approach as this seems to underming C++ type safety.
That''s not true. If you pass a container that has nodes of incompatible type, the compiler will complain. What the templates enable is polymorphism in a broader sense.

You can also try what Magmai Kai Holmlor said, but I don''t really know if there are any benefits of passing iterator instead of container here. Just another place where you''ll end up always writing "x.begin(), x.end()" IMO. Surely it''s more generic once again since you can pass any range or some stranger iterators (like reverse_iterator), but I doubt that''d ever be useful.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.