473,387 Members | 1,548 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

BST with polymorphic data

Hi everyone,
I've to write my own definition of a BST with polymorphic data, as an
university course project.
I have troubles about comparing data when it's defined as polymorphic
pointer.
In my situation I've something like:
class A {}
class B : public A {}
class C : public A {}

and a BST allocated as bst<A*>

how should I discern when i've to compare pointers (as the example) or
objects (as bst<Bfor example)?
Thanks in advance and sorry for my english.
Nov 17 '07 #1
8 1624
Angelwings wrote:
Hi everyone,
I've to write my own definition of a BST with polymorphic data, as an
university course project.
I have troubles about comparing data when it's defined as polymorphic
pointer.
In my situation I've something like:
class A {}
class B : public A {}
class C : public A {}

and a BST allocated as bst<A*>
Since we have no idea what the bst<template looks like, the last piece of
information is by and large useless.

how should I discern when i've to compare pointers (as the example) or
objects (as bst<Bfor example)?
Huh? How would a bst<Bcome up if you have a bst<A*>?

Anyway, here is a suggestion on how to separate concerns: first implement a
basic_bst<Ttemplate that does not support polymorphism at all. Instead it
presupposes the existence of a binary predicate

bool less_than ( T lhs, T rhs )

or

bool less_than ( T const & lhs, T const & rhs )

and does all comparison through that predicate. (Of course, you would be
reinventing the wheel at this point, since the associative standard
containers implement exactly this.)

Then, define a forwarding comparison predicate:

bool less_than ( A const * lhs, A const * rhs ) {
assert ( lhs != 0 );
assert ( rhs != 0 );
return ( polymorphic_less( *lhs, *rhs ) );
}

And finally define

bool polymorphic_less ( A const & lhs, A const & rhs )

in a way appropriate for comparing objects of types derived from A. Note
that the const-reference parameters preserve the dynamic type.

Now, you can use basic_bst<A*to store non-null A* which will be compared
through comparison of pointees. Finally, you can write your polymophic
bst<Aas a wrapper around basic_bst<A*essentially changing the interface
from using non-null A* to A&.

Note: There is one major issue that you will have to deal with, namely
whether objects shall be copied into the search tree or whether the search
tree just holds pointers to the original objects (this ought to be
mentioned somewhere in the specs). In the first case, you would need to
clone the objects as you populate the tree and you would need to dispose of
them when they are removed.
Best

Kai-Uwe Bux
Nov 17 '07 #2
Huh? How would a bst<Bcome up if you have a bst<A*>?
the binary search tree has to work with every type. I'm going to write
with more details the exercise.
Premise: I know it's exactly what an stl tree does, but since it's a
didactic exercise we have to implement it by ourself, without using
stl library.

The exercise consists to define a template of a container, with
minimal operations of insertion, search and erasing.
Then we have to define a class hierarchy that use the container. So I
defined something like i wrote before:

class A {}
class B : public A {}
class C : public A {}

Since every object A, B, C, could be inside the container at runtime,
I have to allocate the bst as bst<A*>. But this is a *particular*
allocation for the exercise. The bst should keep his generalization.

The problem comes when I've to compare objects inside a method of the
bst. If they are allocated as objects there's no problem; they are
compared by their operators. But if they are pointers, they are
compared with their address. I want to dereference them in that case
to use comparing operators of the objects they point.

Here's an example:

template <class T>
void BinarySearchTree<T>::recInsert(Node<T>* root, const T& value) {
if (value < root->info)
if (root->left == 0)
root->left = new Node<T>(value, root);
else
recInsert(root->left, value);
else
if (root->right == 0)
root->right = new Node<T>(value, root);
else
recInsert(root->right, value);
}// recInsert

if the value is a pointer, the addresses are compared instead of
objects.
I've read I could use a functor in the bst template, to define a
custom comparison function. Is that a correct way? Where could I find
a good example to know how I could use a functor in my case? (I
googled it a few yesterday but I didn't find a good explanation)

thanks.
Nov 18 '07 #3
Angelwings wrote:
>Huh? How would a bst<Bcome up if you have a bst<A*>?
the binary search tree has to work with every type. I'm going to write
with more details the exercise.
Premise: I know it's exactly what an stl tree does, but since it's a
didactic exercise we have to implement it by ourself, without using
stl library.

The exercise consists to define a template of a container, with
minimal operations of insertion, search and erasing.
Then we have to define a class hierarchy that use the container. So I
defined something like i wrote before:

class A {}
class B : public A {}
class C : public A {}

Since every object A, B, C, could be inside the container at runtime,
I have to allocate the bst as bst<A*>. But this is a *particular*
allocation for the exercise. The bst should keep his generalization.

The problem comes when I've to compare objects inside a method of the
bst. If they are allocated as objects there's no problem; they are
compared by their operators. But if they are pointers, they are
compared with their address. I want to dereference them in that case
to use comparing operators of the objects they point.
[snip]
I've read I could use a functor in the bst template, to define a
custom comparison function. Is that a correct way?
It is the way that is used in the STL. It has proven to be feasible.
Where could I find
a good example to know how I could use a functor in my case? (I
googled it a few yesterday but I didn't find a good explanation)
What do you mean by "use a functor"? That can refer to two things (at
least):

a) How to implement bst<so that it allows for customization of the
comparison by a user-provided functor.

b) How to write a functor that will forward comparison to pointees.
Best

Kai-Uwe Bux
Nov 18 '07 #4
What do you mean by "use a functor"? That can refer to two things (at
least):
Sorry I know nothing about functors :)
>
a) How to implement bst<so that it allows for customization of the
comparison by a user-provided functor.
this one. I've seen it's the standard way in the stl library. I've
seen some examples and I've seen they overload the operator(). But I
don't want to just copy 'n' paste. I want to understand what I'm
doing. I'd like to read a complete explanation on how they work. I'll
look more on google but if you know a good place to learn them you'll
make to me a great favor to link me the site thanks!
Nov 18 '07 #5
Angelwings wrote:
>
>What do you mean by "use a functor"? That can refer to two things (at
least):
Sorry I know nothing about functors :)
>>
a) How to implement bst<so that it allows for customization of the
comparison by a user-provided functor.
this one.
Ok.
I've seen it's the standard way in the stl library. I've
seen some examples and I've seen they overload the operator(). But I
don't want to just copy 'n' paste. I want to understand what I'm
doing. I'd like to read a complete explanation on how they work. I'll
look more on google but if you know a good place to learn them you'll
make to me a great favor to link me the site thanks!
The basic idea is to no hard-code the comparison. For instance, consider the
function you posted:

template <class T>
void BinarySearchTree<T>::recInsert(Node<T>* root, const T& value) {
if (value < root->info)
if (root->left == 0)
root->left = new Node<T>(value, root);
else
recInsert(root->left, value);
else
if (root->right == 0)
root->right = new Node<T>(value, root);
else
recInsert(root->right, value);
}// recInsert
In the line

if ( value < root->info )

you have hard-coded the comparison. Instead, consider this:

if ( this->is_less( value, root->info ) )

This uses a member object (is_less) to do the comparison. Naturally, for
this syntax to work, the member object is_less will need an overloaded
operator()( T const & lhs, T const & rhs ). However, done this way, the
semantics of the comparison will depend on the _value_ of is_less.
Now, the question arises, what the type of is_less will be. There are two
main alternatives:

a) is_less could be a function pointer

bool (*) ( T const &, T const & )

b) the type is_less could be passed to bst as a template parameter.

The second is more flexible. It is usually done like this:
template < typename T, typename Comp = std::less<T
class bst {

...
Comp is_less;

public:

bst ( Comp pred = Comp() )
: is_less ( pred )
{}

...

};

Note the default-type for Comp and the default value for pred. Taken
together, they ensure that writing

bst<Ttree;

creates a tree that does comparison like the first version.
Best

Kai-Uwe Bux
Nov 18 '07 #6
Thanks a lot for the complete and clear example.

Seeing I'll need to search datas within the tree I thought to define a
compare functor that returns a value < 0 if a < b, a value 0 if a >
b and 0 otherwise. Is it a standard way? Or it's better to use a
second argument in the template for the equality?
Nov 19 '07 #7
Angelwings wrote:
Thanks a lot for the complete and clear example.

Seeing I'll need to search datas within the tree I thought to define a
compare functor that returns a value < 0 if a < b, a value 0 if a >
b and 0 otherwise. Is it a standard way? Or it's better to use a
second argument in the template for the equality?
The standard associative containers only use one comparison predicate and
operate on the premise that
either a < b
or b < a
or a == b

That is, if neither a < b nor b < a, the two elements will be treated as
equivalent (e.g. std::set will not insert b if a is already in the set).

One nice thing about this approach is that it will let the container operate
on elements of type vector<T>, list<T>, ... provided T has a comparison
predicate: all standard containers define a comparison predicate in terms
of comparison of their elements.
On the other hand, a three-way comparison function with values in {-1,0,1}
is clearly a viable alternative. You can even provide a default defined in
terms of "<" and overloads for std::string and standard containers.
Best

Kai-Uwe Bux
Nov 19 '07 #8
Thank you a lot, it works perfectly.
Nov 20 '07 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

37
by: Mike Meng | last post by:
hi all, I'm a newbie Python programmer with a C++ brain inside. I have a lightweight framework in which I design a base class and expect user to extend. In other part of the framework, I heavily...
4
by: Maurice Termeer | last post by:
Hi, suppose i've got this: class a { public: int n; }; class b : public a { public: };
20
by: verec | last post by:
One problem I've come accross in designing a specific version of auto_ptr is that I have to disntiguish between "polymorphic" arguments and "plain" ones, because the template has to, internally,...
1
by: verec | last post by:
Last week I asked here how I could detect that a T was polymorphic, and received very thoughtful and useful replies that I used straight away. Thanks to all who answered. This week, it turns...
7
by: Mr. Ed | last post by:
I have a base class which has about 150 derived classes. Most of the derived classes are very similar, and many don't change the base class at all. All the derived classes have a unique factory...
7
by: James Fortune | last post by:
In response to different users or situations (data context) I transform the appearance and characteristics of Access Forms through code. This seems to fit in with the idea of polymorphism. Do...
12
by: Bob | last post by:
Hi, 'Shadowed' properties are not polymorphic. (See thread 'Inheritance and late binding') They should be. Problem: Base class has read only property 'X'. Derived class must have read / write...
11
by: Angus | last post by:
I am developing a server which receives a range of different messages. There are about 12 different message types so I thought that a good idea would be to devise a class for each message type....
7
by: Arindam | last post by:
#include <cstdio> struct Test { void bar() { foo(); } private: virtual void foo() { printf("Test\n"); }
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.