Heterogeneous Container Library (HCL) Feedback and Testing

I send out a little feeler about a month ago for interest in a container library which natively allows users to insert a heterogeneous set of types. After getting some really good feedback, I think I have settled into something that is efficient, has a nice clean interface, and provides some useful capabilities. I am hoping people can take a look at the code, test it out, and provide an additional feedback in terms of interface, implementation, bugs, or additional features/classes that would be useful. I have implemented a set of containers which mimic the capabilities of the STL containers. These are (so far) * heterovector * heterostack * heteroqueue * heterolist * heteroforward_list * heterodeque These containers were implemented using variadic templates and were somewhat inspired from the posts of Joaquín Muñoz. http://bannalia.blogspot.com/2014/05/fast-polymorphic-collections.html http://bannalia.blogspot.com/2014/05/fast-polymorphic-collections-with.html In addition, I have an adaptor class which provides a simple interface for accessing data of a specific type from a container of type_erased objects (boost::any, boost::variant, etc). The code is hosted at https://github.com/armstrhu/HCL and the directory structure there should be simple to navigate. There is an include directory which contains the header files needed, and an examples directory which provides examples for using the containers and the adaptors. As they mimic the STL containers, once you see how to use them (basically just provide an additional template parameter) you should be able to use them smoothly. One note is I focused mainly on developing the heterovector class, and the remainders are primarily copies of that class where std::vector has been replaced with std::deque, std::list, etc, and associated methods added/removed as needed. I have primarily tested with the heterovector, so having people check out the other classes would be nice :) Any and all feedback is much appreciated. Thanks! -- James Armstrong

2015-06-02 23:41 GMT+02:00 James Armstrong <armstrhu@gmail.com>:
I send out a little feeler about a month ago for interest in a container library which natively allows users to insert a heterogeneous set of types. After getting some really good feedback, I think I have settled into something that is efficient, has a nice clean interface, and provides some useful capabilities. I am hoping people can take a look at the code, test it out, and provide an additional feedback in terms of interface, implementation, bugs, or additional features/classes that would be useful.
I have implemented a set of containers which mimic the capabilities of the STL containers. These are (so far)
* heterovector * heterostack * heteroqueue * heterolist * heteroforward_list * heterodeque
These containers were implemented using variadic templates and were somewhat inspired from the posts of Joaquín Muñoz.
http://bannalia.blogspot.com/2014/05/fast-polymorphic-collections.html http://bannalia.blogspot.com/2014/05/fast-polymorphic-collections-with.html
In addition, I have an adaptor class which provides a simple interface for accessing data of a specific type from a container of type_erased objects (boost::any, boost::variant, etc).
The code is hosted at
https://github.com/armstrhu/HCL
and the directory structure there should be simple to navigate. There is an include directory which contains the header files needed, and an examples directory which provides examples for using the containers and the adaptors. As they mimic the STL containers, once you see how to use them (basically just provide an additional template parameter) you should be able to use them smoothly.
One note is I focused mainly on developing the heterovector class, and the remainders are primarily copies of that class where std::vector has been replaced with std::deque, std::list, etc, and associated methods added/removed as needed. I have primarily tested with the heterovector, so having people check out the other classes would be nice :)
Any and all feedback is much appreciated. Thanks!
Hi James, I think I missed your previous announcement, so pardon me if I am asking something you have already explained. What is the typical use case you are trying to address, fromthe example on GitHub, I gather that: heterogeneous::heterovector<int, double, std::string, double> hv; Is an alternative to: struct vectors { std::vector<int> ints; std::vector<double> doubles; std::vector<std::string> strings; std::vector<double> doubles1; } hv; Does it offer any advantages over the latter? Could you compare them, so that I know what I ain by switching to your library? Regards, &rzej

On Wed, Jun 3, 2015 at 9:24 AM, Andrzej Krzemienski <akrzemi1@gmail.com> wrote:
Hi James, I think I missed your previous announcement, so pardon me if I am asking something you have already explained. What is the typical use case you are trying to address, fromthe example on GitHub, I gather that:
heterogeneous::heterovector<int, double, std::string, double> hv;
Is an alternative to:
struct vectors { std::vector<int> ints; std::vector<double> doubles; std::vector<std::string> strings; std::vector<double> doubles1; } hv;
Does it offer any advantages over the latter? Could you compare them, so that I know what I ain by switching to your library?
Regards,
&rzej
Andrzej, Thanks for the response. So yes, your example would provide pretty much the same functionality. The heterocontainers would then be just a clean interface to allow users to access the data without having to have an ints0, ints1, int2, floats0, float1 and so forth in the struct. Maybe not completely unique thing, but one could argue that a tuple<int,doubl,float> provides not much in additional benefit over what you could do with a class tuple { int int_; double double_; float float_; }; and defining a few methods to access that data. My original idea was to have a container which does not require the user to explicitly declare what data types the container will hold up front. Then, for example, one could easily store insert the results of a database query where the return type is not known at compile time. After some discussion, it was determined that rather than having a dedicated container for this, having generic methods which work with any sequence container of boost::any/boost:variant or similar would be more flexible. That is provided in the adaptor.hpp header with examples in example_adaptor.cpp. There seemed to be some decent interest in the polymorphic collections concept, and while what I have done isn't exactly the same, I think it is close in concept. I figured it wasn't too much work so I went ahead and did that as well. -- James Armstrong

2015-06-03 21:55 GMT+02:00 James Armstrong <armstrhu@gmail.com>:
On Wed, Jun 3, 2015 at 9:24 AM, Andrzej Krzemienski <akrzemi1@gmail.com> wrote:
Hi James, I think I missed your previous announcement, so pardon me if I am asking something you have already explained. What is the typical use case you
are
trying to address, fromthe example on GitHub, I gather that:
heterogeneous::heterovector<int, double, std::string, double> hv;
Is an alternative to:
struct vectors { std::vector<int> ints; std::vector<double> doubles; std::vector<std::string> strings; std::vector<double> doubles1; } hv;
Does it offer any advantages over the latter? Could you compare them, so that I know what I ain by switching to your library?
Regards,
&rzej
Andrzej,
Thanks for the response. So yes, your example would provide pretty much the same functionality. The heterocontainers would then be just a clean interface to allow users to access the data without having to have an ints0, ints1, int2, floats0, float1 and so forth in the struct. Maybe not completely unique thing, but one could argue that a tuple<int,doubl,float> provides not much in additional benefit over what you could do with a
class tuple { int int_; double double_; float float_; };
and defining a few methods to access that data.
My original idea was to have a container which does not require the user to explicitly declare what data types the container will hold up front. Then, for example, one could easily store insert the results of a database query where the return type is not known at compile time. After some discussion, it was determined that rather than having a dedicated container for this, having generic methods which work with any sequence container of boost::any/boost:variant or similar would be more flexible. That is provided in the adaptor.hpp header with examples in example_adaptor.cpp. There seemed to be some decent interest in the polymorphic collections concept, and while what I have done isn't exactly the same, I think it is close in concept. I figured it wasn't too much work so I went ahead and did that as well.
Could you provide some sketch of a real life scenario? The examples show how I can use it, but I fail to imagine why I would need it. You mentioned storing the results of various DB queries, how would you make use of data stored in such way? Reards, &rzej

On Wed, Jun 3, 2015 at 2:42 PM, Andrzej Krzemienski <akrzemi1@gmail.com> wrote:
Could you provide some sketch of a real life scenario? The examples show how I can use it, but I fail to imagine why I would need it. You mentioned storing the results of various DB queries, how would you make use of data stored in such way?
Reards, &rzej
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
I put together a simple example below. I have used a querying library that returns results in a similar fashion. // Define some classes class Paper {//...}; class Notepad {//...}; class Folder {//...}; class Trash {//...}; class Cookie {//...}; class Candy {//...}; class Stapler {//...}; class Coin {//...}; class database { public: enum class OBJECT_TYPES { PAPER, NOTEPAD, FOLDER, TRASH, COOKIE, CANDY, STAPLER, COIN }; bool peek() { return index >= data.size() ? false : true; } OBJECT_TYPES type(size_t column) { return types_[column]; } template<typename T> T* next() { return static_cast<T*>( data[index++] ); } private: std::vector<OBJECT_TYPES> types_; std::vector<void*> data; size_t index; }; using drawer = std::vector<boost::any>; bool add_object( drawer& D, database& db ) { if ( !db.peek() ) return false; switch ( db.type() ) { case database::OBJECT_TYPES::PAPER: D.push_back( db.next<Paper>() ); break; case database::OBJECT_TYPES::NOTEPAD: D.push_back( db.next<Notepad>() ); break; case database::OBJECT_TYPES::FOLDER: D.push_back( db.next<Folder>() ); break; // continue for all OBJECT_TYPES } return true; } int main() { std::vector<drawer> cabinet; size_t num_drawers = 3; cabinet.resize(num_drawers); std::vector<database> db; db.resize(num_drawers); // connect to remote database and run query // pull results from database for (size_t d=0; d<num_drawers; ++d) { while( add_object(cabinet[d], db[d]) ); } // parse cabinet objects below ... // Maybe, we want to count all loose change size_t money = 0; for (size_t d=0; d<num_drawers; ++d) for( auto iter = cabinet[d].begin<Coin>(); iter < cabinet[d].end<Coin>; ++iter ) money += *iter.value(); std::cout << "Found " << money << " cents worth of loose change in cabinet...Score!" << std::endl; return 0; } So yes, at some point you will need to know all object types that can be returned as a result, but, one doesn't need to worry about all the types that are actually returned as a result. Therefore, they can store all possible objects in each of the drawers simply without having to say, my drawer can hold Paper, Notepad, Folder, Trash, etc... and provides a clean way to bundle all of these objects. -- James Armstrong

eerrr...found a couple errors in that previous code. The database class should be class database { public: enum class OBJECT_TYPES { PAPER, NOTEPAD, FOLDER, TRASH, COOKIE, CANDY, STAPLER, COIN }; bool peek() { return index >= data.size() ? false : true; } OBJECT_TYPES type() { return types_[index]; } template<typename T> T* next() { return static_cast<T*>( data[index++] ); } private: std::vector<OBJECT_TYPES> types_; std::vector<void*> data; size_t index; }; won't guarantee the code will actually compile anywhere, but the gist of it is there. -- James Armstrong

I'm having a long day I guess...I forgot to put in anything using the heterogeneous adaptor, the code given before doesn't make any sense...forget my last two posts and see below instead. I'll repeat my comments also... I put together a simple example below. I have used a querying library that returns results in a similar fashion. // Define some classes class Paper {//...}; class Notepad {//...}; class Folder {//...}; class Trash {//...}; class Cookie {//...}; class Candy {//...}; class Stapler {//...}; class Coin {//...}; class database { public: enum class OBJECT_TYPES { PAPER, NOTEPAD, FOLDER, TRASH, COOKIE, CANDY, STAPLER, COIN }; bool peek() { return index >= data.size() ? false : true; } OBJECT_TYPES type() { return types_[index]; } template<typename T> T* next() { return static_cast<T*>( data[index++] ); } private: std::vector<OBJECT_TYPES> types_; std::vector<void*> data; size_t index; }; using drawer = std::vector<boost::any>; bool add_object( drawer& D, database& db ) { if ( !db.peek() ) return false; switch ( db.type() ) { case database::OBJECT_TYPES::PAPER: D.push_back( *db.next<Paper>() ); break; case database::OBJECT_TYPES::NOTEPAD: D.push_back( *db.next<Notepad>() ); break; case database::OBJECT_TYPES::FOLDER: D.push_back( *db.next<Folder>() ); break; // continue for all OBJECT_TYPES } return true; } int main() { std::vector<drawer> cabinet; size_t num_drawers = 3; cabinet.resize(num_drawers); std::vector<database> db; db.resize(num_drawers); // connect to remote database and run query // pull results from database for (size_t d=0; d<num_drawers; ++d) { while( add_object(cabinet[d], db[d]) ); } // parse cabinet objects below ... // Maybe, we want to count all loose change size_t money = 0; for (size_t d=0; d<num_drawers; ++d) { heterogeneous::adaptor HA(cabinet[d]); for( auto iter = HA.begin<Coin>(); iter != HA.end<Coin>; ++iter ) money += *iter.value(); } std::cout << "Found " << money << " cents worth of loose change in cabinet...Score!" << std::endl; return 0; } So yes, at some point you will need to know all object types that can be returned as a result, but, one doesn't need to worry about all the types that are actually returned as a result. Therefore, they can store all possible objects in each of the drawers simply without having to say, my drawer can hold Paper, Notepad, Folder, Trash, etc... and provides a clean way to bundle all of these objects. -- James Armstrong

03.06.2015 23:42, Andrzej Krzemienski:
Could you provide some sketch of a real life scenario? The examples show how I can use it, but I fail to imagine why I would need it. You mentioned storing the results of various DB queries, how would you make use of data stored in such way?
For example, It can be used as fast drop-in replacement for std::vector<boost::variant<Types...>> in case when order of elements (across different types) is not important. For instance CAD application may want to process all objects, like draw all of them or apply some filter or serialize. There is no need to pay cost of dynamic dispatch on each element. By the way, https://akrzemi1.wordpress.com/2013/12/11/type-erasure-part-iii/#comment-175... Best Regards, Evgeny Panasyuk

2015-06-04 0:48 GMT+02:00 Evgeny Panasyuk <evgeny.panasyuk@gmail.com>:
03.06.2015 23:42, Andrzej Krzemienski:
Could you provide some sketch of a real life scenario? The examples show how I can use it, but I fail to imagine why I would need it. You mentioned storing the results of various DB queries, how would you make use of data stored in such way?
For example, It can be used as fast drop-in replacement for std::vector<boost::variant<Types...>> in case when order of elements (across different types) is not important. For instance CAD application may want to process all objects, like draw all of them or apply some filter or serialize. There is no need to pay cost of dynamic dispatch on each element.
A replacement for std::vector<boost::variant<Types...>> in order to get performance -- agreed. Not a "drop-in" one though, I think, because If I change the type, I need to go and change every place that is using it, right? And if I am forced to restructure my code, why would I not just use: struct variantvector { std::vector<T1> t1; std::vector<T2> t2; }; ? In other words, I am not questioning the idea of the optimization, but the usefulness of the library. My understanding (as of now) is that compared to a hand-crafted solution it offers (1) different names for the sub-containers, and (2) a function that returns the sum of sizes of individual containers. Regards, &rzej
By the way, https://akrzemi1.wordpress.com/2013/12/11/type-erasure-part-iii/#comment-175...
Best Regards, Evgeny Panasyuk
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

05.06.2015 12:20, Andrzej Krzemienski:
For example, It can be used as fast drop-in replacement for std::vector<boost::variant<Types...>> in case when order of elements (across different types) is not important. For instance CAD application may want to process all objects, like draw all of them or apply some filter or serialize. There is no need to pay cost of dynamic dispatch on each element.
A replacement for std::vector<boost::variant<Types...>> in order to get performance -- agreed. Not a "drop-in" one though, I think, because If I change the type, I need to go and change every place that is using it, right?
I agree, "drop-in" is wrong wording. I intended to say that there is great intersection of cases where both are applicable, but HCL is more efficient.
And if I am forced to restructure my code, why would I not just use:
struct variantvector { std::vector<T1> t1; std::vector<T2> t2; };
?
In other words, I am not questioning the idea of the optimization, but the usefulness of the library. My understanding (as of now) is that compared to a hand-crafted solution it offers (1) different names for the sub-containers, and (2) a function that returns the sum of sizes of individual containers.
List of element types can be a parameter to code, so a lot of code can be written in generic way. Adding new type of object (with same generic interface as others) into CAD application would not require to change every piece of code which processes or stores them Same applies to boost::variant, and even to "classic OO" - it's just general polymorphism considerations. For example: hcl::vector<Types> v, z; // ... for_each(v, [&](auto &x) { draw(x); // ... if(something(x)) push_back(z, x); }); // ... for_each(z, [](auto &x)) { serialize(x); }); -- Evgeny Panasyuk

2015-06-05 14:02 GMT+02:00 Evgeny Panasyuk <evgeny.panasyuk@gmail.com>:
05.06.2015 12:20, Andrzej Krzemienski:
For example, It can be used as fast drop-in replacement for
std::vector<boost::variant<Types...>> in case when order of elements (across different types) is not important. For instance CAD application may want to process all objects, like draw all of them or apply some filter or serialize. There is no need to pay cost of dynamic dispatch on each element.
A replacement for std::vector<boost::variant<Types...>> in order to get performance -- agreed. Not a "drop-in" one though, I think, because If I change the type, I need to go and change every place that is using it, right?
I agree, "drop-in" is wrong wording. I intended to say that there is great intersection of cases where both are applicable, but HCL is more efficient.
And if I am forced to restructure my code, why would I not just use:
struct variantvector { std::vector<T1> t1; std::vector<T2> t2; };
?
In other words, I am not questioning the idea of the optimization, but the usefulness of the library. My understanding (as of now) is that compared to a hand-crafted solution it offers (1) different names for the sub-containers, and (2) a function that returns the sum of sizes of individual containers.
List of element types can be a parameter to code, so a lot of code can be written in generic way. Adding new type of object (with same generic interface as others) into CAD application would not require to change every piece of code which processes or stores them Same applies to boost::variant, and even to "classic OO" - it's just general polymorphism considerations.
For example: hcl::vector<Types> v, z; // ... for_each(v, [&](auto &x) { draw(x); // ... if(something(x)) push_back(z, x); }); // ... for_each(z, [](auto &x)) { serialize(x); });
Ok, I understand. I wish what I was told in this thread was synthesized and displayed in the introduction page or in documentation. Also, the for_each you presented, perhaps it should be part of this library's interface? Regards, &rzej

05.06.2015 15:28, Andrzej Krzemienski:
Same applies to boost::variant, and even to "classic OO" - it's just general polymorphism considerations.
For example: hcl::vector<Types> v, z; // ... for_each(v, [&](auto &x) { draw(x); // ... if(something(x)) push_back(z, x); }); // ... for_each(z, [](auto &x)) { serialize(x); });
Ok, I understand. I wish what I was told in this thread was synthesized and displayed in the introduction page or in documentation. Also, the for_each you presented, perhaps it should be part of this library's interface?
Yes, of course it should be in library. I presumed that it was already there, but I didn't checked. And I think not just for_each - such kind of library should contain (several/many) algorithms + containers, not just containers. Best Regards, Evgeny Panasyuk

On June 2, 2015 5:41:04 PM EDT, James Armstrong <armstrhu@gmail.com> wrote:
I have implemented a set of containers which mimic the capabilities of the STL containers. These are (so far)
* heterovector * heterostack * heteroqueue * heterolist * heteroforward_list * heterodeque
Why do you have both a namespace and a "hetero" prefix? That's redundant. I cannot imagine a use case for any of these. Rather than have a set of containers, each targeted to a specific data type, your interface uses one type that must be specialized in every use, including member function calls. The former does require naming each container, but that leads to more readable, simpler code in my mind. Can you provide any motivating examples for using these containers which demonstrate their benefits over ad hoc containers?
In addition, I have an adaptor class which provides a simple interface for accessing data of a specific type from a container of type_erased objects (boost::any, boost::variant, etc).
This class seems to provide a little syntactical sugar over an any-based container, so I can imagine some benefit. ___ Rob (Sent from my portable computation engine)

On Tue, Jun 2, 2015 at 11:41 PM, James Armstrong <armstrhu@gmail.com> wrote:
I send out a little feeler about a month ago for interest in a container library which natively allows users to insert a heterogeneous set of types. After getting some really good feedback, I think I have settled into something that is efficient, has a nice clean interface, and provides some useful capabilities. I am hoping people can take a look at the code, test it out, and provide an additional feedback in terms of interface, implementation, bugs, or additional features/classes that would be useful.
I have implemented a set of containers which mimic the capabilities of the STL containers. These are (so far)
* heterovector * heterostack * heteroqueue * heterolist * heteroforward_list * heterodeque
Hi, I didn't get into details yet, I have questions: 1. did you consider providing the same containers without asking for types? In most of my usage of such containers I don't know which types will get in in the end because the container is shared between different "modules" all inserting data inside. maybe a heterovector<> type that would take anything would be useful to others too? 2. did you consider other kinds of non-standard containers? I think in the discussion you linked I posted examples of heterogeneous containers I use in production that do not have equivalents in std. From memory: a container of 1 value or none for each type, not more, the type(id) being the key to access the value.

Le 02/06/15 23:41, James Armstrong a écrit :
I send out a little feeler about a month ago for interest in a container library which natively allows users to insert a heterogeneous set of types. After getting some really good feedback, I think I have settled into something that is efficient, has a nice clean interface, and provides some useful capabilities. I am hoping people can take a look at the code, test it out, and provide an additional feedback in terms of interface, implementation, bugs, or additional features/classes that would be useful.
I have implemented a set of containers which mimic the capabilities of the STL containers. These are (so far)
* heterovector * heterostack * heteroqueue * heterolist * heteroforward_list * heterodeque
Any and all feedback is much appreciated. Thanks!
Hi, Have you considered to provide access to some kind of containers views that behave like standard containers | heterovector<int, double, std::string, double> hv; hv.view<int>.push_back(2); hv.|||view<int>.|push_back(3.1415); // defaults to first double element hv.view<double, 0>.|||push_back|(9); // specifically denote first double element auto hvi =|||hv.view<int>;| // print all integers for (auto itr =|||hvi|.begin(); itr != hvi.end(); ++itr) std::cout << *itr << std::endl;| In this way you will be able to use any algorithm of the standard library. Best, Vicente

Hey guys, Thanks for the feedback and questions... 1. did you consider providing the same containers without asking for types?
In most of my usage of such containers I don't know which types will get in in the end because the container is shared between different "modules" all inserting data inside. maybe a heterovector<> type that would take anything would be useful to others too?
This was the original concept. There is the adapter class which allows access to any container of type_erased datatypes such as boost::any or boost::variant. With this option, one does not need explicitly declare all types that can be stored. 2. did you consider other kinds of non-standard containers?
I think in the discussion you linked I posted examples of heterogeneous containers I use in production that do not have equivalents in std. From memory: a container of 1 value or none for each type, not more, the type(id) being the key to access the value.
With the adaptor class, any non-standard container can be used. The other classes are more or less created for individually for each container type. There may be a clever way over completely generalize this, but I haven't thought of a way yet. Same applies to boost::variant, and even to "classic OO" - it's just
general polymorphism considerations.
For example: hcl::vector<Types> v, z; // ... for_each(v, [&](auto &x) { draw(x); // ... if(something(x)) push_back(z, x); }); // ... for_each(z, [](auto &x)) { serialize(x); });
Ok, I understand. I wish what I was told in this thread was synthesized and displayed in the introduction page or in documentation. Also, the for_each you presented, perhaps it should be part of this library's interface?
Yes, of course it should be in library. I presumed that it was already there, but I didn't checked. And I think not just for_each - such kind of library should contain (several/many) algorithms + containers, not just containers.
I agree this would be a very useful feature. I just finished adding it, will work on implementing everything within <algorithm>. I will try to think of other algorithms that can be applied usefully to the whole container, any other suggestions? Have you considered to provide access to some kind of containers views that
behave like standard containers
Yes, there is a method container() which returns a pointer to the underlying container from which you can use any function designed for the STL containers. Now that you bring this up, having this makes pretty much everything else redundant. I think I will rename this to get<T,N=0> and have the interface be as you suggested...much simpler and easier to maintain. hv.get<int,1>().push_back(5); for (auto itr = hv.get<double>().begin(); itr != hv.get<double>().end() ++itr) cout << *itr << "\n"; -- James Armstrong

On Mon, Jun 8, 2015 at 6:12 PM, James Armstrong <armstrhu@gmail.com> wrote:
Hey guys,
Thanks for the feedback and questions...
1. did you consider providing the same containers without asking for types?
In most of my usage of such containers I don't know which types will get in in the end because the container is shared between different "modules" all inserting data inside. maybe a heterovector<> type that would take anything would be useful to others too?
This was the original concept. There is the adapter class which allows access to any container of type_erased datatypes such as boost::any or boost::variant. With this option, one does not need explicitly declare all types that can be stored.
I'm not sure my understanding is correct, are suggesting to do something like: heterovector<any> ? It would defeat the whole point of the container's characteristics.
2. did you consider other kinds of non-standard containers?
I think in the discussion you linked I posted examples of heterogeneous containers I use in production that do not have equivalents in std. From memory: a container of 1 value or none for each type, not more, the type(id) being the key to access the value.
With the adaptor class, any non-standard container can be used. The other classes are more or less created for individually for each container type. There may be a clever way over completely generalize this, but I haven't thought of a way yet.
Sorry I have trouble understanding what you mean here. If you are suggesting using adapter class over heterosomething, it would be ok if there was some kind of associative container, which would then be able to contain <type_index, SomeType>, to allow me to make an adaptor class tha twould match the container I described. Or maybe I just don't understand your answer.

On June 8, 2015 12:12:12 PM EDT, James Armstrong <armstrhu@gmail.com> wrote:
Have you considered to provide access to some kind of containers views
that behave like standard containers
Yes, there is a method container() which returns a pointer to the underlying container from which you can use any function designed for the STL containers.
Why would you return a pointer? Can it be null? If so, under what circumstances?
Now that you bring this up, having this makes pretty much everything else redundant.
Exactly
I think I will rename this to get<T,N=0> and have the interface be as you suggested...much simpler and easier to maintain.
hv.get<int,1>().push_back(5);
That won't be as useful for non-numeric keys if you have associative containers.
for (auto itr = hv.get<double>().begin(); itr != hv.get<double>().end() ++itr) cout << *itr << "\n";
for (auto d : hv.get<double>()) { std::cout << d << '\n'; } ___ Rob (Sent from my portable computation engine)

On Tue, Jun 2, 2015 at 5:41 PM, James Armstrong <armstrhu@gmail.com> wrote:
After getting some really good feedback, I think I have settled into something that is efficient, has a nice clean interface, and provides some useful capabilities. I am hoping people can take a look at the code, test it out, and provide an additional feedback in terms of interface, implementation, bugs, or additional features/classes that would be useful.
Unless I missed something, I don't see anything that deletes container_ on destruction in heterovector's implementation. And the two delete's that are there (in setEQUALTO) are wrong. You can't delete a void* directly. (Why is it a void*, anyway?) Moreover, I don't understand the chosen implementation strategy at all. As far as I can see, this can be implemented simply by storing a `std::tuple<std::vector<Ts>...>`. All that's needed is something that finds the index of the Nth T in Ts..., which is easy to write. Tim
participants (7)
-
Andrzej Krzemienski
-
Evgeny Panasyuk
-
James Armstrong
-
Klaim - Joël Lamotte
-
Rob Stewart
-
Tim Song
-
Vicente J. Botet Escriba