|
|
Comments and Discussions
|
|
 |

|
I've been using your fine library for some time. I recently have been converting software over to use of BOOST shared_ptrs for all of the memory management benefits that it brings. Therefore, I thought that converting my unique_tree TCL uses over to have shared_ptrs would be as simple as changing the unique_tree typedef to: typedef unique_tree<boost::shared_ptr<myclass>, less<boost::shared_ptr<myclass>, MyClassIntValueCompare>; unique_tree_type; with the comparison function changed to accept shared_ptr<myclass>& instead of MyClass&. Unfortunately, it doesn't compile, complaining about find_deep function signature match problem. Is there something I'm missing? modified on Friday, February 27, 2009 8:36 PM <div class="ForumMod">modified on Friday, February 27, 2009 8:41 PM</div>
|
|
|
|

|
Thanks for your compliment on the TCL.
Could you send me or post the exact error message your getting from the compiler?
Also, what compiler and version are you using, and can you tell me the version of TCL you're using?
The latest version of the TCL is 5.3.0.
|
|
|
|

|
The latest 5.3.0 TCL version is in place. The compiler is VC++2008, Version 9.0.30729.1 SP, .Net Framework 3.5, SP1 The compile error occurs on the call to find_deep as: if ((unique_tree_type::const_iterator) thisTree.find_deep( shared_ptr<myClass> myClassInstPtr ) ) != thisTree.end() The Error Text: : error C2664: 'tcl::associative_iterator<stored_type,tree_type,tree_pointer_type,container_type,pointer_type,reference_type> tcl::unique_tree<stored_type,node_compare_type,node_order_compare_type>::find_deep(const stored_type &)' : cannot convert parameter 1 from 'boost::shared_ptr<T>' to 'const boost::shared_ptr<T> &'
|
|
|
|

|
Hi CodeSeeker,
I'm suspecting that this may be a const-correctness issue, from the error you're getting...
cannot convert parameter 1 from 'boost::shared_ptr<T>' to 'const boost::shared_ptr<T> &'
Could you try changing your comparison operation/functor to use a const reference rather than a reference, and see if that helps?
I'm not sure if you're using a function or function object, but either would work...
bool MyClassIntValueCompare(const shared_ptr<myclass>& lhs, const shared_ptr<myclass>& rhs) { return lhs->somefunction() < rhs->somefunction(); }
or
struct MyClassIntValueCompare
{
bool operator() (const shared_ptr<myclass>& lhs, const shared_ptr<myclass>& rhs) const {return lhs->somefunction() < rhs->somefunction(); }
};
If this isn't the issue, you might try breaking down the code where you're getting the error into two lines, instead of doing an explicit cast to a const iterator. The compiler may be having problems performing that explicit cast during the comparison to thisTree.end().
unique_tree_type::const_iterator it = thisTree.find_deep(shared_ptr<myClass>(myClassInstPtr));
if (it != thisTree.end()) {
...
}
|
|
|
|

|
Is there any way to obtain a child iterator for the root of a tree? The reason I ask is that I am wrapping child iterators inside another class, as pointers to nodes in the tree (and allow next_sibling/previous_sibling operations as well as parent/first_child operations).
Thanks.
|
|
|
|

|
Hello Scott,
Since child iterators need a parent, there's no way to do this. However, there are a couple of alternatives.
1)
You could have a 'virtual root' node. This would be a single child node within the root, which could be used as the 'working' root of the tree. Of course, calling the node's is_root() function would return false for this node, so you could make up a function isRoot() for the elements that you're storing in the tree, and set this member in the virtual root to true, so calling this element function would return true for the virtual root.
2)
You could use pre-order or level-order iterators instead of child iterators.
By nature, descendant iterators contain the calling node in their traversal. Pre and level order iterators traverse the called node as the first node of the iteration, and the post order iterator traverses the called node on the last node of the iteration.
I hope this helps.
|
|
|
|

|
Hi Mitchel,
Thanks very much for your response. I already had your first alternative in mind as a backup plan, and I think it is the approach I will take. Your second alternative is interesting. Using the level-order iterator would do the job, but would require a little more checking. (For example, a next_sibling operation would just require incrementing the level-order iterator, but requires a check to see if there actually is a next sibling).
Again, thanks for the response and thanks for the cool library.
|
|
|
|

|
Thanks for the library. I have a couple of questions.
1. How do I go from one type of iterator to another - I need to go 'down the tree' till I get a particular node/element and then find all the siblings for that node/element. Is there a way to construct a child-iterator from the pre-order iterator (and vice-versa)?
2. What is your approach to possibly extending the library? In my application, I need to have the concept of a tree node 'collapsed' (its child nodes not visible) or 'expanded'. I can have this as the property of the item at that node and not make any change to the tree; or see this as a property/state of the node/tree. In the latter case, a conditional deep iteration can be defined as skipping children if a node if the node is collapsed.
Looking forward to answers/ideas.
|
|
|
|

|
Hello Rajas,
I'm glad you like the library.
1)
There is a way to switch back between regular and descendant iterators.
To switch from a descendant to regular iterator, use the descendant iterator's base() operation. A description of the operation and example of using it is in the latest documentation. You can get the latest docs (and version of the library) at http://www.datasoftsolutions.net/tree_container_library/documentation.php[^].
To switch from a iterator to descendant iterator, just use the node() operation of the iterator, and create a descendant iterator from the node.
it.node()->pre_order_begin(); // here, 'it' is a regular iterator.
By nature, calling pre-order or level-order descendant begin() on any node will return a descendant iterator to the called node, since the called node is always part of a descendant traversal.
Again, there are examples for this in the documentation. Please see the Jan 1, 2008 'Development History' notes on this behavior in the documentation for more info on how and why the called node is contained in the descendant iterator's traversal path.
2)
It would be very hard to customize the library to do selective iteration. A better idea would be continue saving the 'expanded/collapsed' state in the element, as you're doing now, then to create your own forward() and reverse() operations, which accept a descendant iterator, and return a descendant iterator. These operations could examine the 'collapsed' state of the underlying element, and 'skip over' that element switching to a regular iterator, then after skipping the appropriate nodes, return a descendant iterator from the resulting iterator.
Let me know if you have any more questions with this idea,
Mitch
|
|
|
|

|
Thanks. I got the documentation and have looked through it now. A clarification on item 2 above.
when I implement this forward(descendant_iterator it) function, I would check the collapsed state. and if collapsed, I would use the base() function to get the regular (child) iterator & then increment it. I would then use the node()->pre_order_begin() to return the descendant_iterator. However, is this logic valid if incrementing the regular (child) iterator gets to the end - that is the collapsed element is the last child of the current node. my forward() function should actually be returning the next sibling of the parent of this node in the next sequence.
If my question is not clear, I can give an example to illustrate.
|
|
|
|

|
It sounds like the best solution for you may be to use regular (child) iterators in a recursive function.
You may try something like below.
To start the process, pass the root node to the function.
Here, it is assumed that the element's you're storing in the tree have the functions isExpanded(), and name().
void populateNode(tcl::tree<MyClass>* node, HTREEITEM hParent)
{
HTREEITEM hCurrent = treeCtrl->insertItem(node->get()->name(), hParent);
if (node->get()->isExpanded()) {
tcl::tree<MyClass>::iterator it = node->begin(), it_end = node->end();
for (; it != it_end; ++it) {
populateNode(it.node(), hCurrent);
}
}
}
|
|
|
|

|
Just wanted to signal that you can extend the line:
This generic example, as well as the library, is compatible with Visual C++ 6.0, 7.0, and 8.0, as well as GCC. For the VC6 compiler, users need to un-check the Enable minimal rebuild option for successful compilation. Also for VC 6.0 users, the normal #pragma warning (disable : xxxx) directive is necessary to avoid the compiler warnings.
with Visual C++ 9.0 ( or better known as Visual Studio 2008). Tried out and they work without problems.
|
|
|
|

|
Thanks Gabor,
Let's hope 2008 SP1 is friendly with the tcl.
|
|
|
|

|
I am having one user control (containing textBox and two buttons) , I want to add
this control as a node in a treeview control
Please help me
|
|
|
|

|
Hello Elahe,
What you would like to do is certainly possible, but is no small task.
To do this, you must first subclass CTreeCtrl, and add a tree container (of your choice) as a data member...
class MyTree : public CTreeCtrl
{
...
private:
tcl::tree<mystoredtype> internal_tree;
...
}
Now, you'll need to add insert, erase, ect operations which will perform work on the internal tree member.
You might also want to add an operation like set_data(tree), where you pass a populated tree container, and the tree control will automatically display the data in the passed tree.
Most inportantly, you'll need to override CTreeCtrl's Expand() operation, so that when expanding, it will look at the internal tree container, and populate the treectrl nodes based on the contents of the internal tree container.
You must be well familiar with CTreeCtrl to attempt a project like this. If you're not, I'd start out by working with sample projects using a CTreeCtrl, and trace through it's Expand() operations, and most of it's other operations, since you'll be changing the behavior of these operations.
You'll also need to include operations to the Tree ctrl to set what text shows up in the nodes, based on the objects stored in the tree container.
Again, this is no easy task, but very possible with some time and work.
Good luck!
Mitch
|
|
|
|

|
To compile under VS.NET 2002 change:
#if defined(_MSC_VER) && _MSC_VER < 1300
to:
#if defined(_MSC_VER) && _MSC_VER <= 1300
Plus there are some errors under VS 2005.
|
|
|
|

|
Hello Harnash,
Thanks for pointing out the issue with VS2002.
Due to the many differences in standard compliancy between Visual Studio's C++ compilers from version 6.0 up to their latest version, I had to include many compiler guards to accomodate VC 6.0. I went to the extra trouble to make the TCL compatible with VC 6.0, because this version was very popular and in the workplace for a very long time, and still is.
Although I do not currently have VS2002 installed, I would agree that changing the < to <= in the guard would solve many of the problems in 2002. I feel, though, that it would create other problems for some of the guards. This is because VS2002 did fix many of the standard compliant issues in the compiler from VC6, but many were still left until VS2003. So, because the compiler guards fix many kinds of standard compliant issues, in VC6, some of those issues would be fixed in VS2002, while others would not. So, some of the guards would need to include VS2002, while others would need to exclude VS2002. I'll need to obtain and install a copy of VS2002 to determine which guards to include and which ones to exclude for VS2002. But to do this, I'll be waiting until I have the time to uninstall the later editions of Visual Studio, install VS2002, then reinstall the later versions, since I don't want to install an earlier version with the later versions installed. It may be a few months before I have the time to do this, and I can email you when I have this completed.
As far as any issue with VS2005, I do regularly compile the TCL with this version, and I don't encounter any issues. Could you be more specific as to what kind of errors you're seeing in VS2005?
Thanks,
Mitch
|
|
|
|
|

|
Hi Harnash,
Sorry it took a while to get back to you... I have a lot going on now.
I took a look at the changes you made, and it looks like I'll need to make most of these changes, and a few more. Some more changes similar to the ones you made need changed as well, but you probably aren't using the features that require those changes to be made. I won't be making all the changes you pointed out, because they would break the TCL for the GCC compiler, which is very standards compliant. So, I'll need to go over all of the include guards and determine which ones need to be changed and which ones don't so that the TCL compiles in VC2002 as well as GCC and the other MS compilers.
This will take a little while, since I'll wait to install VS2002 on my new machine later this spring.
Until then, it looks like you've made the necessary changes to get the TCL compiling in VS2002 for your needs.
I'll be happy to send you an email when the changes have been made, and add you to the Credits page on the TCL's web site.
Thanks again, and look for the new VS2002 compatible version later this spring, which will include the needed changes you pointed out,
Mitch
|
|
|
|
|

|
Maybe I'm missing something but didn't find any implementation of a "move" operation. Basically I would like to move a "subtree" from one node to another. Taking the Alpha sample from the documentation let's say that I want to move the subtree under "C" from the original node below "L". Is there any possibility to do this?
Thanks' in advance,
Andras
|
|
|
|

|
Hello Andras,
The TCL is closely modeled after the containers in the STL. Since each node is a subtree/container itself, moving a subtree from one node to another would be like moving elements from one container to another in the STL, which is not allowed.
A solution would be to make a temporary copy of the node you wish to move, erase it, then insert it into the desired node.
I'm aware that this solution would be somewhat more expensive than 'moving' the elements, but this solution would be in accordance with STL rules.
In the sample example you mentioned, the snippet below, placed at the bottom of load_tree(), will 'move' node C to node L.
// copy node C to temp, then erase it
it = alpha_tree.end();
--it;
T temp(*it.node());
alpha_tree.erase(it);
// locate node L
it = alpha_tree.begin(); // at node A
it = it.node()->begin(); // at node D
++it; // at node E
it = it.node()->begin(); // at node L
// insert copy of node C in node L
it.node()->insert(temp);
|
|
|
|

|
Hy there !
I'm using your tree container in a project and first I was using it under a Visual Studio 2005 simple version. However when I moved my code to a Visual Studio 2005 with Service Pack 1 installed i got some really crazy errors that said there is different declaration and definition off the templates.
After a few hour digging on the net and code I found the problem. As I thought your code is working without mistakes, but there is a Microsoft bug. Namely take a look at [url=http://support.microsoft.com/default.aspx/kb/930198]this[/url] Hotfix. After you install the HotFix there isn't any further issues. I post this here so you could add this to the download section of the Documentation (Hep Files). This way when a new user meats this particular error it won't scare him away from this nice library or it won't wast a few hours with searching the problem/solution.
Just want to improve ! Have a nice day !
|
|
|
|

|
Hi Gabor,
I appreciate you taking the time to not only look into the issue, but to find the root of the issue and a fix for it.
Since I currently use VC2003 for all my development work, and only use the express editions of VS2005 and VS2008, I would not have found this issue myself. I also use GCC in an Eclipse environment to insure compatibility with that compiler. And since GCC is highly standards compliant, insures that the TCL meets those standards.
I updated the documentation on the site and also the download-able documentation with this info as you advised. Changes have been made to the download page and credits page on the site, and also to the Compiling Options and Credits page in the download-able documentation. I'll be updating this article and the documentation in this article very soon.
Thanks again for hunting this down, and hope the library is working good for you if you're using it in any of your projects!
Mitch
|
|
|
|

|
You are welcome, I wasted a few hours myself of figuring out the source of the problem. It seemed strange to me that first I compiled on a Visual 2005 Standard Edition without the SP1. So I started looking over the code and it seemed OK, and as on Visual 2008 beta compiled also, I thought that it will be some version conflict,this way was the problem found.
As seen that the solution worked I wanted to share with you to so the other people using this code and stuck with the same error code so they won't need to waste some additional time in pursuit of the solution.
Glad I could help, and what more can I say that it's working perfectly in my project. Keep up the good work.
As side note, I just remarked that I made a typo upon registration and by this I wrote at my name Benat instead of Bernat. Edited. Sorry.
modified on Saturday, February 02, 2008 6:30:03 PM
|
|
|
|
 |
|
|
General News Suggestion Question Bug Answer Joke Rant Admin
|
A generic template class library for storing data in a tree-like structure.
| Type | Article |
| Licence | Zlib |
| First Posted | 19 Jan 2006 |
| Views | 134,299 |
| Downloads | 4,823 |
| Bookmarked | 102 times |
|
|