Are there any generic components in Boost (or elsewhere) for *directly* representing associations between classes? Generalization, composition, aggregation and association are major ideas in the object model. Generalization can be implemented fairly directly in C++ using inheritance. Composition and aggregation can be represented directly in C++ using data members (when the number of parts in each whole is small and fixed), or using STL containers (when the number of parts in each whole is large or variable). But Standard C++ (including the STL) provides no *direct* support for representing associations, i.e., collections of links between objects in two or more classes. (David Papurt makes this point in "Inside the Object Model: The Sensible Use of C++.") For example, the STL does not offer a way to *directly* represent the 1-to-many "Supervises" association from the Manager class to the Employee class. One would like to have links in both directions: forward links forthe employees a manager supervises and a back link to the manager each employee is supervised by. Of course, one could code this all "by hand" using a container of pointers to employees for each manager and a back pointer for each employee. But the implementation details really have little to do with managers and employees and would be pretty much the same for parents and children or teachers and students. Moreover, while not difficult, managing the forward and back links correctly (and in an exception-safe manner) is tedious. It would be nice to have templates that can be instantiated to implement specific associations. In brief, STL containers directly support composition and aggregation but not association. I am new to the Boost library, but was not able to find this capability in Boost. If an association library is available in Boost (or elsewhere), I would be happy to know so. If not, is an association library something that would be worth looking into? Thanks, Rob Zako
Hello
class RuntimeAssoc
{
std::map
Are there any generic components in Boost (or elsewhere) for *directly* representing associations between classes?
Generalization, composition, aggregation and association are major ideas in the object model. Generalization can be implemented fairly directly in C++ using inheritance. Composition and aggregation can be represented directly in C++ using data members (when the number of parts in each whole is small and fixed), or using STL containers (when the number of parts in each whole is large or variable). But Standard C++ (including the STL) provides no *direct* support for representing associations, i.e., collections of links between objects in two or more classes. (David Papurt makes this point in "Inside the Object Model: The Sensible Use of C++.")
For example, the STL does not offer a way to *directly* represent the 1-to-many "Supervises" association from the Manager class to the Employee class. One would like to have links in both directions: forward links forthe employees a manager supervises and a back link to the manager each employee is supervised by. Of course, one could code this all "by hand" using a container of pointers to employees for each manager and a back pointer for each employee. But the implementation details really have little to do with managers and employees and would be pretty much the same for parents and children or teachers and students. Moreover, while not difficult, managing the forward and back links correctly (and in an exception-safe manner) is tedious. It would be nice to have templates that can be instantiated to implement specific associations.
In brief, STL containers directly support composition and aggregation but not association.
I am new to the Boost library, but was not able to find this capability in Boost. If an association library is available in Boost (or elsewhere), I would be happy to know so.
If not, is an association library something that would be worth looking into?
Thanks, Rob Zako
Info: http://www.boost.org Wiki: http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl Unsubscribe: mailto:boost-users-unsubscribe@yahoogroups.com
Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
hicks wrote:
There was an intersting article in C++ User's Journal last year containing an implemetation of a many-to-many mapping class.
Yes, this was in the September 2001 issue of the C/C++ User's Journal (p. 40): Extending the Standard Template Library with Association Classes, by Eli Tilevich. Very good article. The code can be downloaded from the CUJ Web Site (http://www.cuj.com). His templates can be used to define one-to-one, one-to-many, or many-to-many relationships that are non-intrusive to the objects that are contained in those relationships. The ManyMany relation also provides for an optional relation attribute (data that properly belongs to the relation, not to to any member of the relation). This code would be a great addition to Boost. Paul Dubuc
Thank you to Craig Hicks (#594) and Paul Dubuc (#601) for your thoughtful answers to my query (#592) re an Association Library. And please pardon my slow reply: Deadlines at work have consumed my time. Craig Hicks wrote:
I am not sure what you mean by "direct". Do you mean compile time? The STL provides an easy way to implement mutable associations at run time (as shown above);
Eli Tilevich in his excellent article in the C/C++ Users Journal (Sept. 2001, p. 40-52) explains the problem as well as I could. In brief, I would like to see a library that allows a programmer to add, modify or remove associations between classes almost as easily as one can add, modify or remove data members, i.e., composition and aggregation relationships. I want to be able to more-or-less directly declare, say, a one-to-many bidirectional relationship between class A and class B without have to rewrite all the boilerplate code for doing so. When requirements change, I want to be able to convert the assocation to a many-to-many association with minimal changes to my application code. Moreover, I don't want to have to worry about the details of maintaining links in both directions, and doing so in an exception-safe manner. (An exception-unsafe implementation would allow a link to be created in one direction without creating a link in the other direction, because an exception -- a low memory condition -- prevented the creation of the reverse link.) Tilevich explains the problem admirably, and his proposed solution is a good step in the right direction. But I think the C++ community would want to extend his solution before adding it to a general-purpose library such as Boost or the STL. In particular, Tilevich's solution uses non-intrusive multimaps to implement associations. While this solution is elegant and flexible, it results in sub-optimal performance compared to an intrusive solution of each object holding its own links to other objects. One of the design goals of the STL is to provide generic code that is close enough in efficiency to handcrafted code that there is rarely a need to handcraft code. Thus if I have, say, a database of 100,000 employees in a large company, I want to be able to define an Employee class and then declare a one-to-many SupervisesAssociation between the Supervisor subclass and the Employee class. (If we assume that each of 10,000 supervisors each supervise roughly 10 employees and that the multimap from supervisors to employees is implemented as some kind of balanced binary tree, then finding the subordinates of a particular supervisor will require O(log N) or roughly 17 accesses. While for most applications this level of performance is acceptable, is falls short of storing links to subordinates directly with each supervisor, which results in O(1) performance.) The following pseudo-code suggests what I have in mind: class Supervisor; class Employee { string name; "Links(many-to-one)<...>" supervisorLinks; }; class Supervisor : public Employee { string department; "Links(one-to-many)<...>" subordinateLinks; }; typedef "One-To-Many<...>" SupervisesAssociation; Here the items in double quotes are meant to be suggestive, not actual code. My intent is to suggest that one could implement this association using just three or so lines of code. If others are interested, I can be more explicit. Moreover, there are more sorts of associations than simply one-to-one, one-to-many and many-to-many. There are two-to-many associations (parent-child), ordered associations (inventor-patent with date, author-publication with date, etc.), undirected associations (for undirected graphs) with associated data, etc. Also, one might not want to realize the time and space costs of using some sort of multimap. For example, if one knows in advance that one object is never assocatiated with more than, say, 4 other objects, then one reasonable approach would be to include a C-style array of 4 (possibly null) pointers with each object. One should be able to do so as an implementation detail -- an option when choosing what kind of association to have -- without having to change client code significantly. The STL already provides this sort of flexibility, for example, with its queue adapter: A queue can be implemented with either a vector or a list. My original question was whether or not Boost or some other generic library provides facilities for implementing associations. The answer I am hearing so far is 1) no, there are no such libraries, and 2) such a capability might be a good addition to Boost. Being a newbie to Boost, I guess my next question is: So how does one go about exploring adding a new capability such as a general-purpose association library to Boost? Thanks, Rob Zako
My original question was whether or not Boost or some other generic library provides facilities for implementing associations. The answer I am hearing so far is 1) no, there are no such libraries, and 2) such a capability might be a good addition to Boost.
I haven't seen one and boost doesn't have one.
Being a newbie to Boost, I guess my next question is: So how does one go about exploring adding a new capability such as a general-purpose association library to Boost?
Read this page :-) http://www.boost.org/more/submission_process.htm Jeff
/My original question was whether or not Boost or some other generic /library provides facilities for implementing associations. The answer I /am hearing so far is 1) no, there are no such libraries, and 2) such a /capability might be a good addition to Boost. /Being a newbie to Boost, I guess my next question is: So how does one /go about exploring adding a new capability such as a general-purpose /association library to Boost? /Thanks, /Rob Zako Actually, such a functionality does exist in Boost. That is because an arbitrary many-to-many mapping with per-node and per-edge data can be represented by a graph which stores per-node and per-edge data. Moreover, the boost graph library is very general in having a lot of parameters, and there is potential for abitrary representations and storage. I have used it mostly as a ready-made storage device and for finding connected components. To get started I pasted and edited large amouts of example code just for the graph object declarations. In some cases the default storage rep (balanced tree list of edges) is not what was required. It some cases the connected components routine as supplied was also not exactly what was required. When neither storage nor function match, what is the advantage in using the library? Answer: If the semantics accompanying the library were simpler, I think that coding to boost::graph specs would be a good way to be sure that ones code was "pattern-compliant", here the pattern being the concept of a graph. But I didn't find that the documentation or example code made that particularly easy, although I intuit that is possible. I hope this isn't seen as gratitous criticism. I wrote to Eli about the graph library, and he remarked that there were plenty of cases where his admittedly specialized code was just what was required, and I agree. rzako23 wrote:
Thank you to Craig Hicks (#594) and Paul Dubuc (#601) for your thoughtful answers to my query (#592) re an Association Library.
And please pardon my slow reply: Deadlines at work have consumed my time.
Craig Hicks wrote:
I am not sure what you mean by "direct". Do you mean compile time? The STL provides an easy way to implement mutable associations at run time (as shown above);
Eli Tilevich in his excellent article in the C/C++ Users Journal (Sept. 2001, p. 40-52) explains the problem as well as I could.
In brief, I would like to see a library that allows a programmer to add, modify or remove associations between classes almost as easily as one can add, modify or remove data members, i.e., composition and aggregation relationships.
I want to be able to more-or-less directly declare, say, a one-to-many bidirectional relationship between class A and class B without have to rewrite all the boilerplate code for doing so. When requirements change, I want to be able to convert the assocation to a many-to-many association with minimal changes to my application code.
Moreover, I don't want to have to worry about the details of maintaining links in both directions, and doing so in an exception-safe manner. (An exception-unsafe implementation would allow a link to be created in one direction without creating a link in the other direction, because an exception -- a low memory condition -- prevented the creation of the reverse link.)
Tilevich explains the problem admirably, and his proposed solution is a good step in the right direction.
But I think the C++ community would want to extend his solution before adding it to a general-purpose library such as Boost or the STL.
In particular, Tilevich's solution uses non-intrusive multimaps to implement associations. While this solution is elegant and flexible, it results in sub-optimal performance compared to an intrusive solution of each object holding its own links to other objects. One of the design goals of the STL is to provide generic code that is close enough in efficiency to handcrafted code that there is rarely a need to handcraft code.
Thus if I have, say, a database of 100,000 employees in a large company, I want to be able to define an Employee class and then declare a one-to-many SupervisesAssociation between the Supervisor subclass and the Employee class.
(If we assume that each of 10,000 supervisors each supervise roughly 10 employees and that the multimap from supervisors to employees is implemented as some kind of balanced binary tree, then finding the subordinates of a particular supervisor will require O(log N) or roughly 17 accesses. While for most applications this level of performance is acceptable, is falls short of storing links to subordinates directly with each supervisor, which results in O(1) performance.)
The following pseudo-code suggests what I have in mind:
class Supervisor;
class Employee { string name; "Links(many-to-one)<...>" supervisorLinks; };
class Supervisor : public Employee { string department; "Links(one-to-many)<...>" subordinateLinks; };
typedef "One-To-Many<...>" SupervisesAssociation;
Here the items in double quotes are meant to be suggestive, not actual code. My intent is to suggest that one could implement this association using just three or so lines of code.
If others are interested, I can be more explicit.
Moreover, there are more sorts of associations than simply one-to-one, one-to-many and many-to-many. There are two-to-many associations (parent-child), ordered associations (inventor-patent with date, author-publication with date, etc.), undirected associations (for undirected graphs) with associated data, etc.
Also, one might not want to realize the time and space costs of using some sort of multimap. For example, if one knows in advance that one object is never assocatiated with more than, say, 4 other objects, then one reasonable approach would be to include a C-style array of 4 (possibly null) pointers with each object. One should be able to do so as an implementation detail -- an option when choosing what kind of association to have -- without having to change client code significantly. The STL already provides this sort of flexibility, for example, with its queue adapter: A queue can be implemented with either a vector or a list.
My original question was whether or not Boost or some other generic library provides facilities for implementing associations. The answer I am hearing so far is 1) no, there are no such libraries, and 2) such a capability might be a good addition to Boost.
Being a newbie to Boost, I guess my next question is: So how does one go about exploring adding a new capability such as a general-purpose association library to Boost?
Thanks, Rob Zako
Info: http://www.boost.org Wiki: http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl Unsubscribe: mailto:boost-users-unsubscribe@yahoogroups.com
Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
rzako23 wrote:
... In particular, Tilevich's solution uses non-intrusive multimaps to implement associations. While this solution is elegant and flexible, it results in sub-optimal performance compared to an intrusive solution of each object holding its own links to other objects. One of the design goals of the STL is to provide generic code that is close enough in efficiency to handcrafted code that there is rarely a need to handcraft code.
I liked the non-intrusive feature. Perhaps better performance could be achieved by replacing the multimaps with sorted vectors following Scott Meyers' advice in Item 23 of this book "Effective STL". -- Paul M. Dubuc
Thank you to everyone for your interest and suggestions.
Following are specific responses to recent postings.
Rob Zako
--- In Boost-Users@y... #683, Jeff Garland
Read this page :-)
Thanks, Jeff!
I believe my next step is to subscribe to the Boost mailing list and
learn more about Boost before I try to add anything myself.
Once I feel confident enough, I will continue a more technical version
of this discussion on that list.
--- In Boost-Users@y... #684, Craig Hicks
Actually, such a functionality does exist in Boost. That is because an arbitrary many-to-many mapping with per-node and per-edge data can be represented by a graph which stores per-node and per-edge data.
Yes, Craig, I have looked quite a bit at the Boost Graph Library.
A lot of thought has gone into this library and it is very general.
But I thought that a graph can represent only an association between
a class and itself, not between two distinct classes. Am I missing
something here?
--- In Boost-Users@y... #719, Paul Dubuc
I liked the non-intrusive feature. Perhaps better performance could be achieved by replacing the multimaps with sorted vectors following Scott Meyers' advice in Item 23 of this book "Effective STL".
Paul, I like the non-intrusive feature, too. My point is that whether or not an association is represented with an intrusive or non-intrusive data structure should be an implementation detail, not a fundamental choice. What I'd like to see is a standard interface (much like the Boost Graph Library provides a standard interface) for dealing with associations. I envision this being done by defining an Association concept. Then different specific classes can realize the Association concept in different ways. But client code need not know which implementation is being used, just so long as the client code assumes only the requirements of the Association. In particular, the distinction between an intrusive and a non-intrusive association should be transparent to client code, and should require modifying but a few lines of code for the involved classes.
rzako23 wrote:
Thank you to everyone for your interest and suggestions.
Following are specific responses to recent postings.
Rob Zako
--- In Boost-Users@y... #684, Craig Hicks
wrote: Actually, such a functionality does exist in Boost. That is because an arbitrary many-to-many mapping with per-node and per-edge data can be represented by a graph which stores per-node and per-edge data.
Yes, Craig, I have looked quite a bit at the Boost Graph Library. A lot of thought has gone into this library and it is very general.
But I thought that a graph can represent only an association between a class and itself, not between two distinct classes. Am I missing something here?
A graph can represent associations between two nodes by means of the edge (or edges) which connect those two nodes. The nodes are, needless to say, distinct objects. It's up to the programmer to design a node data type which can capture the necessary information to distinguish between nodes. Obviously what I'm saying is obvious, so I think it's my turn to say "I'm missing your point". and ask for clarification. Are you saying it would be useful to have a bipartite graph (or N-partite graph) with each part holding seperate types? Is that how Tevich's association library worked? I can't recall. I dare say the BGL (or any C++ based graph) could handle nodes with different data types via inheritance (all nodes contain a pointer to base data class). Regardless, the issue of classes is one of syntax. My statement was meant semantically, without regard to syntax. 1.Do you agree with the statement "Any implementation of an many-many assoication container must have an underlying graph lurking within (semantically speaking)"? 2.Do you agree with the statement "The BGL is capable of being the uderlying mechanism for implementing a many-many class (e.g., one with the I/F defined by Telvich's interface) ? I'm fairly certain about 1, and think 2 is correct, but am not certain especially since I don't have Tevich's class at hand right now. The 3rd question is, if it can be implemented with BGL, is it worth it? You'd be able to reuse the exchangeability of data structures. You'd have a host of algorithms available. Anything new you developed might be reused for graphs in general. You'd have more time to concentrate on the I/F. Craig Hicks
[Non-text portions of this message have been removed]
Dear Craig,
--- In Boost-Users@y... #757, Craig Hicks
A graph can represent associations between two nodes by means of the edge (or edges) which connect those two nodes. The nodes are, needless to say, distinct objects. It's up to the programmer to design a node data type which can capture the necessary information to distinguish between nodes. Obviously what I'm saying is obvious, so I think it's my turn to say "I'm missing your point", and ask for clarification. ...
I don't know who's missing what, but I could have been more clear before and will attempt to be so now. I'll also provide a somewhat realistic example, which is what you originally asked for (in message #594). Consider an application used by a school for keeping track of students, courses, teachers, rooms, books, meals, buses and other objects that are part of the school. The application uses a Student class: class Student { int id; string name; string address; Date birthdate; ... }; The Student class has a lot of data members, and there are a lot of (member and free) functions for handling students. Indeed, there is an extensive graphical user interface that allows the user to add, modify, delete and find students maintained by the application. The application also uses a Course class: class Course { int number; string name; string description; string instructor; string room; string meeting_times; ... }; Like the Student class, the Course class has a lot of data members, and there are a lot of (member and free) functions for handling course. And there is an extensive graphical user interface that allows the user to add, modify, delete and find courses maintained by the application. What I want you to imagine is that there are two independent and well-developed classes that do not yet have an association between them. One might even imagine -- as is actually realistic -- that the two classes are parts of different applications written by different programmers. Of course, requirements change and software evolves. At some point, there is a requirement to associate students and courses: to keep track of which students are enrolled in which classes. Obviously, this is a many-to-many association. As I understand it, in order to use the BGL -- indeed to use any graph library with which I am familiar -- one would have to derive both the Student and Course classes from some common base class: class SchoolObject { ... }; class Student : public SchoolObject { ... }; class Course : public SchoolObject { ... }; Then one could create a graph for which each node is a SchoolObject. While this approach might work, it is unnatural. A Student is not a Course, and there really is no such concept as a "SchoolObject" in the application domain. Indeed, such an approach would allow links (graph edges) between students and students, or between courses and courses -- neither of which makes sense. Thus there would need to be source code to explicitly forbid such illogical links. There are two main problems with using the BGL (or any general-purpose graph library with which I am familiar). First, a mathematically idealized graph generally does not distinguish between nodes of different types: Any node can be linked to any other node via an edge. The same can be said of computer implementations of graphs. In brief, a graph is typically an association between a type (class) and itself. Yes, mathematically, one can consider bipartite graphs in which nodes can be classified into different classes. But the graph libraries I have seen do not implement this idea as a graph involving two different (C++) classes of nodes. Second, the graph libraries I am familiar with emphasize abstract nodes linked by edges. The nodes and edges may each have data associated with them (the BGL does this using property maps), but the data associated with nodes and edges is considered secondary. In effect, the idea of a graph makes the association primary and the participating class(es) of nodes (objects) secondary. But in typical applications -- as I try to indicate in my example -- the emphasis is the object. The classes of objects (students and courses) are primary and are predetermined. One does not have the flexibility to recode these classes to conform to, say, the BGL, the Graph Template Library (GTL) or some other graph library. The association between the classes is a relatively minor detail, and associations can be added, modified or removed from an application perhaps more frequently than the classes of objects themselves. I am looking for a library that allows me to take the preexisting Student and Course classes and to add an Enrollment association between the two with but minimal modification of existing source code.
Are you saying it would be useful to have a bipartite graph (or N-partite graph) with each part holding separate types? Is that how Tilevich's association library worked? I can't recall.
Yes, as I note above, I am saying it would be useful to have a
bipartite graph, i.e., a graph with nodes in two different classes.
Yes, this is how Tilevich does it in the Sept. 2001 C/C++ Users Journal
article. He gives an example involving employees and projects, which is
conceptually the same as my example involving students and courses:
ManyMany
I dare say the BGL (or any C++ based graph) could handle nodes with different data types via inheritance (all nodes contain a pointer to base data class).
Yes, I think it could. But as I note above, it is unnatural to derive fundamentally different classes from some artificial base class. Moreover, in so doing, you allow for unnatural edges linking, say, a student to a student rather than to a course.
Regardless, the issue of classes is one of syntax. My statement was meant semantically, without regard to syntax.
1. Do you agree with the statement "Any implementation of an many-many assoication container must have an underlying graph lurking within (semantically speaking)"?
Yes, I agree, if one allows that the underlying graph may be a bipartite graph that has nodes in two different classes.
2. Do you agree with the statement "The BGL is capable of being the underlying mechanism for implementing a many-many class (e.g., one with the I/F defined by Tilevich's interface) ?
I'm fairly certain about 1, and think 2 is correct, but am not certain especially since I don't have Tilevich's class at hand right now.
Yes, it is capable of being the underlying mechanism. But it is also true that it is possible to write an object-oriented program with inheritance, polymorphism and virtual functions in plain C. It is possible, but it is not very natural or convenient. The point of the STL -- and I believe of Boost extensions of the STL -- is to make common but involved tasks *easy* by providing templates that are efficient and easy to use.
The 3rd question is, if it can be implemented with BGL, is it worth it? You'd be able to reuse the exchangeability of data structures. You'd have a host of algorithms available. Anything new you developed might be reused for graphs in general. You'd have more time to concentrate on the I/F.
This question gets at my point about graphs emphasizing the association, i.e., the edges, whereas most C++ application classes that participate in associations are emphasized more than than the associations between them. To put it a different way, much of the functionality that a graph library provides -- beyond being a mechanism for implementing the association -- is not desired. Would one do a depth-first or breadth-first search of the graph students and courses? What would that mean and what use would it be? Would one want to find connected components, i.e., clusters of students and courses that form a kind of school-within-a-school? One could do that, but it would not be high on the list of requirements for a school management application. What is desired is being able to access "neighbors": all the courses a particular student is enrolled in or all the students enrolled in a particular course. But oned oes *not* need an entire graph library to achieve this low-level functionality. One just needs an association library. And that is what I seek: An efficient, flexible, easy-to-use association library that allows me to add, modify and delete different kinds of associations (1-to-1, 1-to-many, many-to-many, unidirectional, bidirectional, etc.) between classes A, B, C, etc., in which some associations are between a class and itself (hence a general graph) but other associations are between distinct classes. Craig, thank you for your good questions and for giving me the opportunity to think out loud. Thanks, Rob Zako P.S. So far we have been discussing only *binary* associations. If we were to discuss ternary and higher-order associations, which link 3 or more objects together, then the idea of an association as a graph would break down.
Dear Craig,
--- In Boost-Users@y... #757, Craig Hicks
wrote: A graph can represent associations between two nodes by means of the edge (or edges) which connect those two nodes. The nodes are, needless to say, distinct objects. It's up to the programmer to design a node data type which can capture the necessary information to distinguish between nodes. Obviously what I'm saying is obvious, so I think it's my turn to say "I'm missing your point", and ask for clarification.
...
I don't know who's missing what, but I could have been more clear before and will attempt to be so now. I'll also provide a somewhat realistic example, which is what you originally asked for (in message #594).
Consider an application used by a school for keeping track of students, courses, teachers, rooms, books, meals, buses and other objects that are part of the school.
The application uses a Student class:
class Student { int id; string name; string address; Date birthdate; ... };
The Student class has a lot of data members, and there are a lot of (member and free) functions for handling students. Indeed, there is an extensive graphical user interface that allows the user to add, modify, delete and find students maintained by the application.
The application also uses a Course class:
class Course { int number; string name; string description; string instructor; string room; string meeting_times; ... };
Like the Student class, the Course class has a lot of data members, and there are a lot of (member and free) functions for handling course. And there is an extensive graphical user interface that allows the user to add, modify, delete and find courses maintained by the application.
What I want you to imagine is that there are two independent and well-developed classes that do not yet have an association between them. One might even imagine -- as is actually realistic -- that the two classes are parts of different applications written by different programmers.
Of course, requirements change and software evolves. At some point, there is a requirement to associate students and courses: to keep track of which students are enrolled in which classes. Obviously, this is a many-to-many association.
As I understand it, in order to use the BGL -- indeed to use any graph library with which I am familiar -- one would have to derive both the Student and Course classes from some common base class:
class SchoolObject { ... };
class Student : public SchoolObject { ... };
class Course : public SchoolObject { ... };
Then one could create a graph for which each node is a SchoolObject.
I was thinking more along the following lines: // reusable code for RTTI based multiclass association class NodeBase { /* common node interface */ }; template <class T> class NodeDerived : public NodeBase; { T *pT; }; // application code for multiclass association typedef NodeDerived<Student> NodeStudent; typedef NodeDerived<Course> NodeCourse; As you can see, I am thinking of a design where all the code that can gets factored into a seperate module for class-generic RTTI-based multiclass association. First and foremost, because this is RTTI, there is no compile time type checking of the derived types. But there is run-time checking, which can also pushed into the reusable class-generic RTTI-based code.
While this approach might work, it is unnatural. A Student is not a Course, and there really is no such concept as a "SchoolObject" in the application domain. Indeed, such an approach would allow links (graph edges) between students and students, or between courses and courses -- neither of which makes sense. Thus there would need to be source code to explicitly forbid such illogical links.
There would need to be such source code, but the hard work could be pushed into the reusable class-generic RTTI-based code.
There are two main problems with using the BGL (or any general-purpose graph library with which I am familiar).
First, a mathematically idealized graph generally does not distinguish between nodes of different types: Any node can be linked to any other node via an edge. The same can be said of computer implementations of graphs. In brief, a graph is typically an association between a type (class) and itself.
Yes, mathematically, one can consider bipartite graphs in which nodes can be classified into different classes. But the graph libraries I have seen do not implement this idea as a graph involving two different (C++) classes of nodes.
Second, the graph libraries I am familiar with emphasize abstract nodes linked by edges. The nodes and edges may each have data associated with them (the BGL does this using property maps), but the data associated with nodes and edges is considered secondary. In effect, the idea of a graph makes the association primary and the participating class(es) of nodes (objects) secondary.
But in typical applications -- as I try to indicate in my example -- the emphasis is the object. The classes of objects (students and courses) are primary and are predetermined. One does not have the flexibility to recode these classes to conform to, say, the BGL, the Graph Template Library (GTL) or some other graph library. The association between the classes is a relatively minor detail, and associations can be added, modified or removed from an application perhaps more frequently than the classes of objects themselves.
I am looking for a library that allows me to take the preexisting Student and Course classes and to add an Enrollment association between the two with but minimal modification of existing source code.
Are you saying it would be useful to have a bipartite graph (or N-partite graph) with each part holding separate types? Is that how Tilevich's association library worked? I can't recall.
Yes, as I note above, I am saying it would be useful to have a bipartite graph, i.e., a graph with nodes in two different classes.
Yes, this is how Tilevich does it in the Sept. 2001 C/C++ Users Journal article. He gives an example involving employees and projects, which is conceptually the same as my example involving students and courses:
ManyMany
Projects;
No question, Tilevich's code is superior in the case of two fixed classes, for those applications whose requirements are completely satisfied by said code.
I dare say the BGL (or any C++ based graph) could handle nodes with different data types via inheritance (all nodes contain a pointer to base data class).
Yes, I think it could. But as I note above, it is unnatural to derive fundamentally different classes from some artificial base class.
Moreover, in so doing, you allow for unnatural edges linking, say, a student to a student rather than to a course.
Regardless, the issue of classes is one of syntax. My statement was meant semantically, without regard to syntax.
1. Do you agree with the statement "Any implementation of an many-many assoication container must have an underlying graph lurking within (semantically speaking)"?
Yes, I agree, if one allows that the underlying graph may be a bipartite graph that has nodes in two different classes.
2. Do you agree with the statement "The BGL is capable of being the underlying mechanism for implementing a many-many class (e.g., one with the I/F defined by Tilevich's interface) ?
I'm fairly certain about 1, and think 2 is correct, but am not certain especially since I don't have Tilevich's class at hand right now.
Yes, it is capable of being the underlying mechanism.
But it is also true that it is possible to write an object-oriented program with inheritance, polymorphism and virtual functions in plain C. It is possible, but it is not very natural or convenient.
The point of the STL -- and I believe of Boost extensions of the STL -- is to make common but involved tasks *easy* by providing templates that are efficient and easy to use.
I will second that "*easy*" statement !!! Providing a "configuration", an interface that specializes a container to make it usable for a particular purpose counts as making it easy. That is definitely a requirement if BGL were to be used to to implement an association class.
The 3rd question is, if it can be implemented with BGL, is it worth it? You'd be able to reuse the exchangeability of data structures. You'd have a host of algorithms available. Anything new you developed might be reused for graphs in general. You'd have more time to concentrate on the I/F.
This question gets at my point about graphs emphasizing the association, i.e., the edges, whereas most C++ application classes that participate in associations are emphasized more than than the associations between them.
To put it a different way, much of the functionality that a graph library provides -- beyond being a mechanism for implementing the association -- is not desired.
If the user-programmer can't see it (hidden by interface), does it exist?
Would one do a depth-first or breadth-first search of the graph students and courses? What would that mean and what use would it be?
Would one want to find connected components, i.e., clusters of students and courses that form a kind of school-within-a-school? One could do that, but it would not be high on the list of requirements for a school management application.
What is desired is being able to access "neighbors": all the courses a particular student is enrolled in or all the students enrolled in a particular course. But oned oes *not* need an entire graph library to achieve this low-level functionality. One just needs an association library.
And that is what I seek: An efficient, flexible, easy-to-use association library that allows me to add, modify and delete different kinds of associations (1-to-1, 1-to-many, many-to-many, unidirectional, bidirectional, etc.) between classes A, B, C, etc., in which some associations are between a class and itself (hence a general graph) but other associations are between distinct classes.
Mostly I want to agree with you as far as the following is true: You have an application all of whose requirements, (present and envisioned future), are satisfied by Telivich's library. Otherwise, you might want to think about the cost/benefits of an RTTI version (with templates) versus a template only version.
Craig, thank you for your good questions and for giving me the opportunity to think out loud.
Thanks, Rob Zako
P.S. So far we have been discussing only *binary* associations. If we were to discuss ternary and higher-order associations, which link 3 or more objects together, then the idea of an association as a graph would break down.
Good point. Craig Hicks
rzako23 wrote:
Consider an application used by a school for keeping track of students, courses, teachers, rooms, books, meals, buses and other objects that are part of the school [...]
As I understand it, in order to use the BGL -- indeed to use any graph library with which I am familiar -- one would have to derive both the Student and Course classes from some common base class:
class SchoolObject { ... };
class Student : public SchoolObject { ... };
class Course : public SchoolObject { ... };
Then one could create a graph for which each node is a SchoolObject.
Nope, that's not the way BGL works. BGL was designed specifically to do the kind of thing you want. Indeed, the BGL distribution contains simple adapters that allow you to use BGL functions on data types defined in other graph packages by "other programmers", e.g. Stanford GraphBase and LEDA. STL containers work differently than BGL graphs, but they don't require a "SchooldObject" base class either. (I don't know of any C++ library that does!) You can create STL containers that contain references (pointers) to objects. The underlying objects are not "part of" or "owned by" the containers, and don't necessarily need to "know" that they are referenced by the containers. BGL graphs are even more detached from application-level semantics. They are pure graph abstractions - opaque edges and vertices, and that's all. If you are holding two distinct BGL edges, they are like two potatoes that are so similar that "the only difference between them is that they are different." The association between edges/vertices and their labels is not part of the graph. Instead, the programmer creates the association using abstract "property maps". You could, for example, use an STL container, such as a map<>, to implement the property map. Frequently, a vector<> or deque<> will suffice. You can have more than one set of labels for a graph, and you can use them simultaneously. For example, you can have one set of labels that implement the application-semantics and another that is used by an algorithm to "mark" vertices as the algorithm inspects them. I highly recommend The Boost Graph Library User Guide and Reference Manual by Jeremy G. Siek, et al. Jive
Dear Jive,
--- In Boost-Users@y..., Jive Dadson
Nope, that's not the way BGL works. BGL was designed specifically to do the kind of thing you want. Indeed, the BGL distribution contains simple adapters that allow you to use BGL functions on data types defined in other graph packages by "other programmers", e.g. Stanford GraphBase and LEDA. ...
Thank you for your comments. If you caught the start of this thread, my original question was whether Boost (or some other template library) allows a programmer to easily implement associations between classes. I admit to being impressed with the power and flexibility of the BGL, but have not fully mastered how to use it. If the BGL can be used to implement associations between classes, I would appreciate learning that. Could you provide a code snippet that shows how to implement my example: the Enrollment association between the preexisting Student and Course classes? Thanks in advance! Rob Zako
My boss says he looked at the boost.org website and found that we must pay a fee per unit sold for any produced that uses the boost library. I say it is completly free, but I can't find anything on the website to back me up. All I have to go on is the copyright agreement at the top of each file. Is there something on the web site I can point him to? TIA --
Your boss must be in an alternative universe :-) Seriously, Boost does not require any fee for use.
From the license requirements page:
--Must grant permission to copy, use and modify the software for any use (commercial and non-commercial) for no fee. http://www.boost.org/more/lib_guide.htm#License Jeff
-----Original Message----- From: Daniel T. [mailto:daniel_t@gorilla.com] Sent: Monday, May 06, 2002 6:20 AM To: Boost-Users@yahoogroups.com Subject: [Boost-Users] Permission to use?
My boss says he looked at the boost.org website and found that we must pay a fee per unit sold for any produced that uses the boost library. I say it is completly free, but I can't find anything on the website to back me up. All I have to go on is the copyright agreement at the top of each file.
Is there something on the web site I can point him to? TIA
--
Info: http://www.boost.org Wiki: http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl Unsubscribe: mailto:boost-users-unsubscribe@yahoogroups.com
Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
On Monday 06 May 2002 09:20 am, you wrote:
My boss says he looked at the boost.org website and found that we must pay a fee per unit sold for any produced that uses the boost library. I say it is completly free, but I can't find anything on the website to back me up. All I have to go on is the copyright agreement at the top of each file.
Is there something on the web site I can point him to? TIA
The Boost library license requirements http://www.boost.org/more/lib_guide.htm#License state: "Must grant permission to copy, use and modify the software for any use (commercial and non-commercial) for no fee." Doug
--- Douglas Gregor
On Monday 06 May 2002 09:20 am, you wrote:
My boss says he looked at the boost.org website and found that we must pay a fee per unit sold for any produced that uses the boost library. I say it is completly free, but I can't find anything on the website to back me up. All I have to go on is the copyright agreement at the top of each file.
Is there something on the web site I can point him to? TIA
The Boost library license requirements http://www.boost.org/more/lib_guide.htm#License
state:
"Must grant permission to copy, use and modify the software for any use (commercial and non-commercial) for no fee."
I believe this is for those that want to /contribute/ to the Boost project rather than those that want to /use/ the libraries. Noel __________________________________________________ Do You Yahoo!? Yahoo! Health - your guide to health and wellness http://health.yahoo.com
On Monday 06 May 2002 10:07 am, you wrote:
The Boost library license requirements http://www.boost.org/more/lib_guide.htm#License
state:
"Must grant permission to copy, use and modify the software for any use (commercial and non-commercial) for no fee."
I believe this is for those that want to /contribute/ to the Boost project rather than those that want to /use/ the libraries.
Noel
Exactly. A library can't be contributed to Boost unless it is free to use in both commercial and noncommercial settings, so every library in Boost is free to use in those settings. Doug
--- Douglas Gregor
The Boost library license requirements
http://www.boost.org/more/lib_guide.htm#License
state:
"Must grant permission to copy, use and modify
On Monday 06 May 2002 10:07 am, you wrote: the
software for any use (commercial and non-commercial) for no fee."
I believe this is for those that want to /contribute/ to the Boost project rather than those that want to /use/ the libraries.
Noel
Exactly. A library can't be contributed to Boost unless it is free to use in both commercial and noncommercial settings, so every library in Boost is free to use in those settings.
IIRC, the original poster was asking what the license agreement was for /users/ of Boost. For example, if I'm creating an application or library for internal use within a bank, can I use Boost within the implementation and under what usage agreements (eg will the application/library have to be open-sourced, ...)? Noel __________________________________________________ Do You Yahoo!? Yahoo! Health - your guide to health and wellness http://health.yahoo.com
On Monday 06 May 2002 10:57 am, you wrote:
IIRC, the original poster was asking what the license agreement was for /users/ of Boost. For example, if I'm creating an application or library for internal use within a bank, can I use Boost within the implementation and under what usage agreements (eg will the application/library have to be open-sourced, ...)?
Noel
Every Boost library has its own license agreement for users. However, minimum requirements for that license agreement are specified at http://www.boost.org/more/lib_guide.htm#License, which specifies in part that each library's license agreement (with the user) "Must grant permission to copy, use and modify the software for any use (commercial and non-commercial) for no fee. " So every Boost library grants permission _to the user_ to copy, use, and modify the software for any use for free. Libraries with more restrictive open-source licenses (e.g., the GNU Public License), are _not_ eligible for inclusion in Boost because they do not meet the Boost license requirements (one of which is "Must not require that the source code be available for execution or other binary uses of the library"). So in your example, using the Boost libraries does _not_ require you to open-source your application or library, because no Boost library is allowed to require that. Doug
--- Douglas Gregor
Every Boost library has its own license agreement for users. However, minimum requirements for that license agreement are specified at http://www.boost.org/more/lib_guide.htm#License, which specifies in part that each library's license agreement (with the user)
"Must grant permission to copy, use and modify the software for any use (commercial and non-commercial) for no fee. "
So every Boost library grants permission _to the user_ to copy, use, and modify the software for any use for free. Libraries with more restrictive open-source licenses (e.g., the GNU Public License), are _not_ eligible for inclusion in Boost because they do not meet the Boost license requirements (one of which is "Must not require that the source code be available for execution or other binary uses of the library").
So in your example, using the Boost libraries does _not_ require you to open-source your application or library, because no Boost library is allowed to require that.
Thanks so much for the clarification. Noel __________________________________________________ Do You Yahoo!? Yahoo! Health - your guide to health and wellness http://health.yahoo.com
At 7:07 AM -0700 5/6/02, Noel Yap wrote:
--- Douglas Gregor
wrote: On Monday 06 May 2002 09:20 am, you wrote:
My boss says he looked at the boost.org website and found that we must pay a fee per unit sold for any produced that uses the boost library. I say it is completly free, but I can't find anything on the website to back me up. All I have to go on is the copyright agreement at the top of each file.
Is there something on the web site I can point him to? TIA
The Boost library license requirements http://www.boost.org/more/lib_guide.htm#License
state:
"Must grant permission to copy, use and modify the software for any use (commercial and non-commercial) for no fee."
I believe this is for those that want to /contribute/ to the Boost project rather than those that want to /use/ the libraries.
Noel
An interesting point. The reason, of course that, this requirement exists is so that users may use the libraries without fee, but, as Noel points out, this statement only implies that, it doesn't say it explicitly. The boost.org home page has the statement "The Boost web site provides free peer-reviewed portable C++ source libraries." Perhaps the word "free" should have a link to a page that explains what users can and cannot do with Boost library sources (with some examples). Or is there some statement about permissions that is directed to users that I have missed? Given the existence to clueless bosses and worse company lawyers I don't think we can be too clear on this point. -- Jon Kalb Kalb@LibertySoft.com
On Monday, May 6, 2002, at 08:42 AM, Jon Kalb wrote:
The boost.org home page has the statement "The Boost web site provides free peer-reviewed portable C++ source libraries." Perhaps the word "free" should have a link to a page that explains what users can and cannot do with Boost library sources (with some examples).
The reason this isn't there is that each library essentially has its own license -- whatever the library author puts in. But we do require that the license meet certain criteria or we won't allow it in Boost, and that criteria is: "Must grant permission to copy, use and modify the software for any use (commercial and non-commercial) for no fee." But there is not a single standard license and thus it's hard to make a clear blanket statement.
Given the existence to clueless bosses and worse company lawyers I don't think we can be too clear on this point.
I think there is room for much improvement, and this has been discussed at length before. Perhaps you can come up with a specific proposal that Boost contributors would agree to. -- Darin
Hi All,
Is there any need in a template wrapping an object of any type, and giving it an extra NULL value ?
This is sometimes necessary :
- When working with database if a column can be NULL.
- When a value may be unspecified.
The idea is to wrap an object in a class that will behave exactly like this object,
except that it will have some extra properties :
- The is_null() and to_null(bool) operators are added.
- Serialization (Operators >> and <<) take into account the "NULL" string.
There are three basic usage :
- The 'null' flag can be stored in the object (Default behaviour).
- The 'null' flag can be a special value : See specialization for pointers (Use of NULL special value),
doubles and float (Using NotANumber NaN special value),
- The 'null' flag and/or the value itself are accessed by the template, giving it a member function
as template parameter.
Please find a test program; The library itself - a single include file - is written and runs on GnuC and VC++ 6.
Thanks.
RC
/*****************************************************************************
** null_tst.cpp
*****************************************************************************/
#include
A similar concept was discussed on the Boost developer list for a class named 'optional'. The notion is the same, except that we did not discuss having a sentinel value to denote 'null'. Instead, it was assumed that the optional<T> class would have a 'null' flag stored in the object. Fernando Cacciola was the author of 'optional', but I don't know what happened to it. It never came up for review. Doug On Monday 06 May 2002 07:37 am, you wrote:
Hi All, Is there any need in a template wrapping an object of any type, and giving it an extra NULL value ? This is sometimes necessary : - When working with database if a column can be NULL. - When a value may be unspecified.
The idea is to wrap an object in a class that will behave exactly like this object, except that it will have some extra properties : - The is_null() and to_null(bool) operators are added. - Serialization (Operators >> and <<) take into account the "NULL" string.
There are three basic usage : - The 'null' flag can be stored in the object (Default behaviour). - The 'null' flag can be a special value : See specialization for pointers (Use of NULL special value), doubles and float (Using NotANumber NaN special value), - The 'null' flag and/or the value itself are accessed by the template, giving it a member function as template parameter.
Please find a test program; The library itself - a single include file - is written and runs on GnuC and VC++ 6.
Thanks. RC
participants (11)
-
Daniel T.
-
Darin Adler
-
Douglas Gregor
-
hicks
-
Jeff Garland
-
Jive Dadson
-
Jon Kalb
-
Noel Yap
-
Paul Dubuc
-
ravioli@softhome.net
-
rzako23