Indexing c++ map with enum class - c++

Is there a way to get the memory/speed benefit of fixed length (known at compile-time) arrays while still having the static error checking and readability provided by enum class when indexing an array?
I exactly want the behavior of the array, except I want to disallow users from indexing by integers. I'd prefer to force writing potentially_descriptive_name[kLogicalRisingEdge] over potentially_descriptive_name[0] as I work with physicists who prioritize new results over writing maintainable codebase since they only need to work on it for 5-7 years before never seeing it again.
I'm hoping to have the ability to quickly iterate over subsets of data an arbitrary number of times (in my field, the filtered subset is called a "cut" of the data), but I need to perform this preprocessing first and I thought it would be great for readability to have an enum for the cut, so I can have something like what's below:
have a header defining the cuts
// data_cuts.h
namespace data_cuts {
enum TimeCut {kInTime, kOutOfTime, kOther, N_elems}; // or enum class : uint?
TimeCut GetTimeCut(const Datum& d);
enum EdgeCut {kRising, kFalling, N_elems}; // sim
EdgeCut GetEdgeCut(const Datum& d);
}
filling the data like this in one part of the project
for (const auto& d : full_data)
data_by_time_cut[GetTimeCut(d)].push_back(datum);
// potentially a much less memory intensive way to do this, but that should be addressed elsewhere
reading said data in another part of the project
using namespace data_cuts;
for (TimeCut cut : std::vector<TimeCut>{kInTime, kOutOfTime})
histograms_by_time_cut[cut].FillN(data_by_time_cut[c]);
for (const auto& d : data_by_time_cut[kInTime])
histograms_by_time_cut[kInTime].FillSpecial(d);
but I don't know how to choose the type for data_by_time_cut and histograms_by_time_cut
Options I can think of, (I think improving as it goes down)
I could use std::map<CutType, T> and enum class CutType and indexing is only permissible with CutType and not numeric-int or another type of cut, but I have all of map's overhead.
I could use std::vector and convert the strongly typed enum to underlying every time I access, but it feels ungainly and it doesn't have the static check for generic integer indexing.
I could use std::array and convert the strongly typed enum to underlying again.
I could [learn how to and] write a template that wraps std::array and overloads operator[](T t) to call to_underlying and then I'm doing the above but less verbose. However, this just seems so generic, is this already implemented in a "better way" in C++14?
This is my attempt at the last option I listed, uses the code found here to define to_underlying
#include <array>
#include <vector>
template <typename E>
constexpr auto to_underlying(E e) noexcept
{
return static_cast<std::underlying_type_t<E>>(e);
}
template <typename T, typename U>
class EnumIndexedArray
{
public:
EnumIndexedArray(){}; // should I add the other constructors?
U& operator[](const T& t) {return m_arr[to_underlying(t)]; };
const U& operator[](const T& t) const {return m_arr[to_underlying(t)]; };
private:
std::array<T, to_underlying(T::N_elems)> m_arr;
};
namespace data_cuts {
enum class TimeCut : char {kInTime, kOutOfTime, kOther, N_elems};
enum class EdgeCut : char {kRising, kFalling, N_elems};
}
class Datum;
class Histogram;
using Data = std::vector<Datum>;
EnumIndexedArray<data_cuts::TimeCut, Data> data_by_time_cut;
EnumIndexedArray<data_cuts::TimeCut, Histogram> histograms_by_time_cut;
I wonder if I'm adding too much for this to be a general question, so I'll stop for now.

Related

What realization to choose for heterogenous container that uses std::variant for data storage?

For a program which is a simple rogue-like game, I need a container for storing contents of each room be it enemies, loot, traps, lore-entries etc. Since set of types being held in each room is finite and predetermined I've settled for std::variant for data storage. I also will need methods to process the data and here comes the problem. Now due to lack of experience I struggle to choose realization that won't become a burden in long term.
Objective style approach:
using myVariant = std::variant<TYpe1, Type2 ... TypeN>;
template <typename V>
class HVector
{
private:
class HVElem
{
private:
V data;
public:
V getData();
};
std::vector<HVElem> content;
public:
void push(V newData);
};
int main()
{
HVector<myVariant> hVector;
}
Functional approach:
using myVariant = std::variant<TYpe1, Type2 ... TypeN>;
template <typename V> void push(std::vector<V> hVector, V newData)
{
// something
}
int main()
{
std::vector hVector<myVariant>;
}
Questions:
Which of the two approaches is better? I have a strong feeling that simply using std::vector<std::variant<>> with some template functions is enough in this case. Is using objective style even requiered here?
How can I prevent the program from creating a container that holds anything other than std::variant<>? Is there a way to simply list types in type aliases so that I could simply write std::vector<std::variant<myTypes>>?
Which of the two approaches is better?
Neither, see option 3 below.
How can I prevent the program from creating a container that holds anything other than std::variant<>?
using myVariant = std::variant<TYpe1, Type2 ... TypeN>;
using myVector = std::vector<myVariant>;

standard interface of iterator::operator* that return more than T& and std::pair

Iterator of each datastructure has different type of return value of operator*() e.g. :-
Most array-like DataStructure<T> : return T&.
std::unordered_map<K,T> : return std::pair<const K, T>&.
const std::unordered_map<K,T> : return const std::pair<K, T>&.
What should be the datatype if my iterator::operator*() want to return something more complex (std::pair is not enough)?
Example
I have a custom 3D datastructure Map3D<T> that is like a map (int,int,int)->T.
To achieve the above requirement, I create a new class Bundle3D<T>.
template<class T>class Bundle3D {
//getInternalIndex1D()
//getCoordinate()
//getValue()
};
The Map3D<T>'s iterator::operator* would have signature like :-
Bundle3D<T> iterator::operator*(){ ... }
Its usage is like :-
Map3D<float> map;
for(auto& ele:map){ //"ele" has some special type named "Bundle"
int keyInternal1DIndex=ele.getInternalIndex1D();
Vector3Int& key=ele.getCoordinate();
float& value=ele.getValue();
}
It works good, but I think my code is not standardized.
In other words, Bundle3D<T>, getInternalIndex1D(), getCoordinate() and getValue() is blindly named by me.
In real case, I have created a lot of custom data-structures that generate such strange iterator.
Question
Is there any std::/standard type of return-value of iterator::operator*(), when T& and std::pair is not enough?
I have doubted about this for several months, but feel very reluctant to ask it.
If this question need improvement, please comment.
Edit
(clarify the word standardized - this part is my subjective notion.)
I feel that all types of standard collection in most language, e.g. :-
java.util.Collection/ArrayList in Java
std::unordered_map/vector in C++
Iterators of all of them have signatures of function getValue() or operator* that return either T or StandardPair<index,T> - no other types.
For many years, I am convinced that it is a rule or a strong convention/tradition that I really should obey.
There must be a reason.
However, I am not sure what it is, because I am probably very new to C++.
If I design my software to return something strange (e.g. Bundle3D<T> in the above example), I think I will get punished hard from the unconventional design. (e.g. not have .first field)
What you have right now is okay. I would just specify one thing that I think isn't very C++-ish and may in fact harm your standardization options in the future.
It's the getters. Obviously you have deep roots in Java, and the concept of public members is abhorred in Java programming, so much so that the concept of "beans" exists. I don't intend to knock on Java here, it's a nice language with its own nice idioms.
But this is C++, with it's own programming idioms. You obviously noticed the direct access to the contents of std::pair. It's like that for a reason. A pair is just two items packed together, that's the sum of its behavior. Getters would just ,well, get in the way. :)
There's no need for them, because we aren't dealing with an "abstraction" of two items bundled together, but instead we really do have a concrete, honest to god, bundle1.
Obviously we can have bundles of more than two items. That's why we have std::tuple. Now while it's true that all access to a tuple is through a non-member function called get, that's simply because there is no way to give names to members of an arbitrarily sized bundle. get still returns a reference to the element, so you retain direct access into the bundle.
This long winded exposition is important, because an upcoming C++1z feature, called "Structured Bindings", relies on the standard behavior of tuples and pairs, as well as how C++ programmers see aggregates. Under this feature, an iteration over a map, will look like this:
#include <map>
#include <iostream>
std::map<char const*, int> foo()
{
return {
{ "foo", 3 },
{ "bar", 7 },
{ "baz", 1 },
};
}
int main() {
for (auto [key, val] : foo()) {
std:: cout << "( " << key << ", " << val << " )\n";
}
return 0;
}
Live example
And the same extends to any user defined bundle of data. Your own return value type in the post can be bound similarly, if the members are public:
struct Vector3Int {};
template<class T>
struct Bundle3D {
int internal_index_id;
Vector3Int const &coord;
T &value;
};
int main() {
Vector3Int vec;
float val;
Bundle3D<float> bundle{ 1, vec, val };
auto[ idx_id, coord, value] = bundle;
// coord = {}; // compile error since coord gets the cv qualifer
}
Live example
So my suggestion is, leave the getters to your Java code, and use aggregates as bundles of data for C++.
1 An aggregate, to be more formal.
I'm going to assume that your Map3D is a spacial co-ordinate to value container.
I would return a std::pair<const Vector3Int, T>&, and not bother with getInternalIndex1D as part of the return. That can be left as a function Vector3Int -> int.
Have a look at UnorderedAssociativeContainer for the sorts of members that would be useful to define
e.g.
template <typename T>
class Map3D
{
using key_type = Vector3Int;
using mapped_type = T;
using value_type = Bundle3D<T>; // Key, Value, Internal1DIndex
using reference = Bundle3D<T> &;
using pointer = Bundle3D<T> *;
using hasher = /*Function object that calculates Internal1DIndex*/
using key_equal = std::equal<Vector3Int>
... iterators, const_* definitions, etc
}

Optimize template replacement of a switch

I have a lot of custom datatypes in one of my projects which all share a common base class.
My data (coming from a database) has a datatype which is distinguished by an enum of the base class. My architecture allows a specific datatype to be specialized with a derived class or it can be handled by the base class.
When I construct one my specific datatypes I normally call the constructor directly:
Special_Type_X a = Special_Type_X("34.34:fdfh-78");
a.getFoo();
There is some template magic which also allows constructing it like this:
Type_Helper<Base_Type::special_type_x>::Type a = Base_Type::construct<Base_Type::special_type_x>("34.34:fdfh-78");
a.getFoo();
For some values of the type enum there might be no specialization so
Type_Helper<Base_Type::non_specialized_type_1>::Type == Base_Type
When I'm fetching data from the database the datatype isn't known at compile time so there's a third way to construct the datatypes (from a QVariant):
Base_Type a = Base_Type::construct(Base_type::whatever,"12.23#34io{3,3}");
But of course I want the correct constructor to be called, so the implementation of that method used to look like:
switch(t) {
case Base_Type::special_type_x:
return Base_Type::construct<Base_Type::special_type_x>(var);
case Base_Type::non_specialized_type_1:
return Base_Type::construct<Base_Type::non_specialized_type_1>(var);
case Base_Type::whatever:
return Base_Type::construct<Base_Type::whatever>(var);
//.....
}
This code is repetitive and since the base class can handle new types (added to the enum) as well, I came up with the following solution:
// Helper Template Method
template <Base_Type::type_enum bt_itr>
Base_Type construct_switch(const Base_Type::type_enum& bt, const QVariant& v)
{
if(bt_itr==bt)
return Base_Type::construct<bt_itr>(v);
return construct_switch<(Base_Type::type_enum)(bt_itr+1)>(bt,v);
}
// Specialization for the last available (dummy type): num_types
template <>
Base_Type construct_switch<Base_Type::num_types>(const Base_Type::type_enum& bt, const QVariant&)
{
qWarning() << "Type" << bt << "could not be constructed";
return Base_Type(); // Creates an invalid Custom Type
}
And my original switch statement is replaced with:
return construct_switch<(Base_Type::type_enum)0>(t,var);
This solution works as expected.
The compiled code is however different. While the original switch statement had a complexity of O(1) the new approach results in a O(n) complexity. The generated code recursively calls my helper method until it finds the correct entry.
Why can't the compiler optimize this properly? Are there any better ways to solve this?
Similar problem:
Replacing switch statements when interfacing between templated and non-templated code
I should mention that I would like to avoid C++11 and C++14 and stick to C++03.
This is what I call the magic switch problem -- how to take a (range of) run time values and turn it into a compile time constant.
Abstractly, you want to generate this switch statement:
switch(n) {
(case I from 0 to n-1: /* use I as a constant */)...
}
You can use parameter packs to generate code that is similar to this in C++.
I'll start with c++14-replacing boilerplate:
template<unsigned...> struct indexes {typedef indexes type;};
template<unsigned max, unsigned... is> struct make_indexes: make_indexes<max-1, max-1, is...> {};
template<unsigned... is> struct make_indexes<0, is...>:indexes<is...> {};
template<unsigned max> using make_indexes_t = typename make_indexes<max>::type;
Now we can create a compile-time sequence of unsigned integers from 0 to n-1 easily. make_indexes_t<50> expands to indexes<0,1,2,3, ... ,48, 49>. The c++14 version does so in O(1) steps, as most (all?) compilers implement std::make_index_sequence with an intrinsic. The above does it in linear (at compile time -- nothing is done at run time) recursive depth, and quadratic compile time memory. This sucks, and you can do better with work (logarithmic depth, linear memory), but do you have more than a few 100 types? If not, this is good enough.
Next, we build an array of callbacks. As I hate C legacy function pointer syntax, I'll throw in some pointless boilerplate to hide it:
template<typename T> using type = T; // pointless boilerplate that hides C style function syntax
template<unsigned... Is>
Base_Type construct_runtime_helper( indexes<Is...>, Base_Type::type_enum e, QVariant const& v ) {
// array of pointers to functions: (note static, so created once)
static type< Base_Type(const QVariant&) >* const constructor_array[] = {
(&Base_Type::construct<Is>)...
};
// find the eth entry, and call it:
return constructor_array[ unsigned(e) ](v);
}
Base_Type construct_runtime_helper( Base_Type::type_enum e, QVariant const& v ) {
return construct_runtime_helper( make_indexes_t< Base_Type::num_types >(), e, v );
}
and Bob is your Uncle1. An O(1) array lookup (with an O(n) setup, which in theory could be done prior to your executable launching) for dispatch.
1 "Bob's your Uncle" is a British Commonwealth saying that says "and everything is finished and working" roughly.
Are all the functions inline? I'd expect a reasonable compiler to optimize the if tree into a switch, but only if the ifs are in the same function. For portability, you might not want to rely on this.
You can get O(1) with an indirect function call by having construct_switch populate a std::vector<std::function<Base_Type(const QVariant&)>> with lambda functions that do the construction and then dispatch off that.

How to read through types of a struct in C/C++

I am trying to find the "types" of any given variables in different structs and be able to read them. (keep in mind this is psuedo code)
For Example:
#include "stream.h" //a custom stream reader class I made
typedef unsigned char BYTE;
/***** SERIES OF DIFFERENT STRUCTS ******/
struct asset
{
char *name;
int size;
BYTE *data;
};
struct asset2
{
char *lang;
char *entry;
};
/*****************************************/
void readAsset( Enumerable<struct> &istruct)
{
foreach( object o in istruct )
{
switch( o )
{
case int:
&o = _stream->ReadInt32();
break;
case char:
&o = _stream->ReadChar();
break;
case *:
&o = _stream->ReadInt32();
break;
default: break;
}
}
}
I want it to be able to do the following:
asset a1;
asset2 a2;
readAsset( a1 );
readAsset( a2 );
and pass all the info from the file to a1 and a2.
I was wondering if there was a way in C/C++ to get the type of the data from any object in the struct then read based on that? is it possible with complex enums? Sorry for the bad code but I wanted it to be easier to understand what I'm trying to do.
Additional Info:
_stream is a pointer to a Stream class I made similar to Stream Reader in .Net It reads data from a file and advances it's position based on how big of data it was read.
I'll be happy to re-phrase if you don't understand what I'm asking.
There is no way to iterate through the members of a structure without listing them all out.
You can iterate through something like a structure at compile time using ::std::tuple in C++11.
You also can't really switch on type in that fashion. You can do it, but the way you do it is to have several functions with the same name that each take a different parameter type. Something like:
void doRead(StreamType &stream, int &data)
{
data = stream.readInt32();
}
void doRead(StreamType &stream, char &data)
{
data = stream.readChar();
}
// etc...
Then you just call doRead with your structure member and poof the compiler magically picks the right one based on the type.
In C++, the way to solve the problem you're solving here is a serialization library. If you have control of both the format written and the format read, you can use something like protobuf or boost::serialization to do this relatively easily without having to write a lot of your own code.
Additionally, a couple of issues with your code. Do not use a leading _ character in identifiers. Identifiers with a leading _ are reserved for use by the compiler or standard library implementation. Many compilers have special keywords that are compiler specific language extensions that start with an _ character. Using identifiers with a leading _ character may result in your code mysteriously failing to compile with all kinds of strange inscrutable errors in some environments.
You can get something like a struct that is enumerable at compile time. But it's ugly:
#include <tuple>
#include <string>
#include <vector>
#include <type_traits>
class asset : public ::std::tuple< ::std::string, ::std::vector<BYTE> >
{
public:
::std::string &name() { return ::std::get<0>(*this); }
const ::std::string &name() const { return ::std::get<0>(*this); }
::std::vector<BYTE> &data() { return ::std::get<1>(*this); }
const ::std::vector<BYTE> &data() const { return ::std::get<1>(*this); }
};
void writeToStream(Stream *out, const ::std::string &field)
{
out->writeString(field);
}
void writeToStream(Stream *out, const ::std::vector<BYTE> &field)
{
out->writeInt(field.size());
out->writeRaw(field.data(), field.size());
}
template <unsigned int fnum, typename... T>
typename ::std::enable_if< (fnum < sizeof...(T)), void >::type
writeToStream_n(Stream *out, const::std::tuple<T...> &field)
{
writeToStream(out, ::std::get<fnum>(field));
writeToStream_n<fnum+1, T...>(out, field);
}
template <unsigned int fnum, typename... T>
typename ::std::enable_if< (fnum >= sizeof...(T)) >::type
writeToStream_n(Stream *, const::std::tuple<T...> &)
{
}
template <typename... Tp>
void writeToStream(Stream *out, const ::std::tuple<Tp...> &composite)
{
writeToStream_n<0, Tp...>(out, composite);
}
void foo(Stream *out, const asset &a)
{
writeToStream(out, a);
}
Notice that there is no explicit writeToStream for the asset type. The compiler will write it at runtime by unpacking the ::std::tuple it's derived from and writing out each individual field.
Also, if you have bare pointers, you're writing poor C++. Please write idiomatic, good C++ if you're going to write C++. This whole thing you want to do with runtime reflection is just not the way to do things.
That's the reason I converted your char *name to a ::std::string and your size delimited BYTE array represented by your size and data fields into a ::std::vector. Using those types is the idiomatically correct way to write C++. Using bare pointers the way you were is not. Additionally, having two fields that have strongly related values (the data and size) fields that have no behavior or any other indication that they're associated would make it hard even for a compiler that does introspection at runtime to figure out the right thing to do. It can't know how big the BYTE array being pointed to by data is, and it can't know about your decision to encode this in size.
What you're asking for is something called Reflection - which is:
the ability of a computer program to examine
and modify the structure and behavior (specifically the values,
meta-data, properties and functions) of an object at runtime.
C++ doesn't have that "natively".
What I mean is - there have been some attempts at introducing some aspects of it - with varied degrees of success - which have produced some aspects of Reflection, but not "full" Reflection itself as you will get in a language like Ruby or so.
However, if you are feeling adventurous, you can try a Reflection library called Reflectabit:
To see if it might be worthwhile (which it might be considering your code), it is referenced here - which has quite a bit of examples on how to use the API:
http://www.altdevblogaday.com/2011/09/25/reflection-in-c-part-1-introduction/
Good luck!
The usual pattern in C++ is not to try and figure out what the members of the type are, but rather provide an operator, implemented by the implementor of the type, that is able to serialize/deserialize to disk.
You can take a look at, for example, the boost::serialize library. The usage is not too complex, you need to provide a function that lists your members in some order and then the library will take it from there and implement serialization to different formats.

Could someone help me create a variable container using Boost::MPL?

I have created a physics system that handles any collision object to any collision object like so:
namespace Collision
{
template <typename T, typename U>
inline void Check(T& t, U& u)
{
if(u.CheckCollision(t.GetCollider()))
{
u.HitBy(t);
t.Hit(u);
}
}
}
and there are several other helper objects to make it easy to use, but the gist is that there are dynamic objects that need to be tested against static objects and other dynamic objects, but static objects don't need to be checked.
What I would like is something like this:
void func()
{
PhysicsWorld world;
shared_ptr<CSphere> ballPhysics(new CSphere(0,0,ballSprite->Width()));
BallCommand ballBehavior;
CBounds bounds(0, 0, 640, 480);
CBox obstacle(200, 150, 10, 10);
Collision::Collidable<CBounds> boundC(bounds);
Collision::Collidable<std::shared_ptr<CSphere>, BallCommand&> ballC(ballPhysics, ballBehavior);
Collision::Collidable<CBox> obstC(obstacle);
world.addStatic(boundC);
world.addDynamic(ballC);
world.addStatic(obstC);
...
...
world.Update();
...
...
}
I'd love to deduce the containers through the add functions so using the system automatically updates the type lists. I think I get how to generate a typelist with a template function, but not how to then get it where I need it, or at what point in compilation it is complete.
If not that then some system using two typelists that then internally writes the update function to iterate through all the lists pairing them up against each other.
I've read some of the boost MPL book and read Andrei's book several times. But, I seem to get caught up in the how it works stuff and don't really translate that into how do I use it. I wish they had one more section on real world examples in the MPL book.
I've been able to get all of the pieces of a game engine to interact with rendering, physics, collisions (I separate detection from reaction), input, network, sound, etc. All in generic ways. Now I just need to hold all the things in a generic way. After all that generic work, it would be silly to require inheritance just so I can hold something in a container and I don't want to hand code every collection possibility as that is one of the great benefits of generic programming.
I saw Jalf had indicated that s/he used MPL to do something similar, but did not go into details enough for me to figure it out. If anyone knows a practical use example or where I can get more info on using the MPL I'd be grateful.
Thanks again!
Update
boost MPL and boost Fusion both seem to do what I want, but there appears to be very little in the way of good real life examples of either libraries. The documentation for MPL is little more than this template does this and good luck understanding the implications of that. Fusion is a bit better with "Here's an example but it's just the tip of the iceberg!"
A typical boost MPL example is has_xxx. They use XXX and xxx in the example making it difficult to see the difference where XXX(The required text) and Test or CheckType or any more distinguishable user type could be used in place of xxx. Plus there is no mention that none of this is in a namespace. Now I know why Scott meyers compared this to the shower scene in Psycho.
It's a shame really because what little I have gotten to compile and understand does really useful things, but is so hard to figure out I would never spend this much effort if I was on a shipping product.
If anyone knows real world examples or better references, explanations, or tutorial I would be grateful.
Update
Here's more code:
template <typename T, typename V = VictimEffect, typename M = MenaceEffect>
class Collidable
{
T m_Collider;
V m_HitBy;
M m_Hit;
public:
Collidable(T collide, V victim, M menace) : m_Collider(collide), m_HitBy(victim), m_Hit(menace) {;}
Collidable(T collide) : m_Collider(collide) {;}
Collidable(T collide, V victim) : m_Collider(collide), m_HitBy(victim) {;}
T& GetCollider()
{
return m_Collider;
}
template <typename V>
void HitBy(V& menace)
{
m_HitBy.HitBy(menace.GetCollider());
}
template <typename V>
void Hit(V& victim)
{
m_Hit.Hit(victim.GetCollider());
}
template <typename V>
bool CheckCollision(V& menace)
{
return m_Collider.CheckCollision(menace);
}
};
Then to use it I do this
Collidable<Boundary, BallCommand> boundC(boundary, ballBehavior);
Collidable<CollisionBox> ballC(circle);
Then all I need is to call collide with all my active collidable objects against all my active and passive objects.
I'm not using std::function because the addition of function names makes the code clearer to me. But maybe that's just legacy thinking.
If I understand correctly your problem is:
class manager {
public:
template<typename T>
void add(T t);
private:
/* ??? */ data;
/* other members? */
};
manager m;
some_type1 s1;
some_type2 s2;
m.add(s1);
m.add(s2);
/* m should hold its copies of s1 and s2 */
where some_type1 and some_type2 are unrelated and you're unwilling to redesign them to use dynamic polymorphism.
I don't think either MPL or Fusion will do what you want with this form. If your problem is what container to use as a member of PhysicsWorld, then no amount of compile-time computations will help: the member type is determined at instantiation time, i.e. the line manager m;.
You could rewrite the manager in a somewhat meta-programing fashion to use it this way:
typedef manager<> m0_type;
typedef typename result_of::add<m0_type, some_type1>::type m1_type;
typedef typename result_of::add<m1_type, some_type2>::type final_type;
/* compile-time computations are over: time to instantiate */
final_type m;
/* final_type::data could be a tuple<some_type1, some_type2> for instance */
m.add(s1); m.add(s2);
This is indeed the sort of things MPL+Fusion can help with. However this still remains quite anchored in the compile-time world: can you imagine writing an template<typename Iter> void insert(Iter first, Iter last) just so you can copy the contents of a container into a manager?
Allow me to assume that your requirements are such that in fact the manager has to be used in a much more runtimey fashion, like in my original formulation of your question. (I don't think that's quite a stretch of the imagination for a PhysicsWorld). There is an alternative, which I think is more appropriate, much less verbose and more maintanable: type-erasure. (The name of the technique may be a bit unfortunate and can be misleading the first time.)
A good example of type-erasure is std::function:
std::function<void()> func;
func = &some_func; /* this just looks like that internally std::function stores a void(*)() */
func = some_type(); /* but here we're storing a some_type! */
Type-erasure is a technique to bridge compile-time with runtime: in both assignments above, the arguments are unrelated types (one of which is non-class so not even remotely runtime polymorphic), but std::function handles both, provided they fulfill the contract that they can be used as f() (where f is an instance of the respective type) and that the expression has type (convertible to) void. The contract here is the compile-time aspect of type-erasure.
I'm not going to demonstrate how to implement type-erasure because there is a great Boostcon 2010 presentation on the subject. (You can watch the presentation and/or get the slides through the link). Or I (or someone else) can do it in the comments.
As a final note, implementation of type-erasure (typically) uses dynamic polymorphism. I mention that because I noticed you considered the use of typelists as a runtime object stored as a manager member. This smells like poor man's reflection, and really, poor man's dynamic polymorphism. So don't do that please. If you meant typelists as in the result of a MPL computation then disregard the node.
This is not complete And I did not get everything I want, but it's good enough for now. I'm entering the whole solution in case it helps others.
#include <boost\mpl\vector.hpp>
#include <boost\mpl\fold.hpp>
#include <boost\mpl\for_each.hpp>
#include <boost\mpl\inherit.hpp>
#include <boost\mpl\inherit_linearly.hpp>
#include <iostream>
#include <vector>
using namespace boost::mpl::placeholders;
typedef boost::mpl::vector<short, long, char, int> member_types;
template <typename T>
struct wrap
{
std::vector<T> value;
};
typedef boost::mpl::inherit_linearly<member_types, boost::mpl::inherit<wrap<_2>, _1> >::type Generate;
class print
{
Generate generated;
public:
template <typename T>
void operator()(T)
{
std::cout << *static_cast<wrap<T>&>(generated).value.begin() << std::endl;
}
template <typename T>
void Add(T const& t)
{
static_cast<wrap<T>&>(generated).value.push_back(t);
}
};
void main()
{
print p;
short s = 5;
p.Add(s);
long l = 555;
p.Add(l);
char c = 'c';
p.Add(c);
int i = 55;
p.Add(i);
boost::mpl::for_each<member_types>(p);
}
This isn't the final object I need, but now I have all the pieces to make what I want.
Update
And finally I get this.
template <typename TL>
class print
{
template <typename T>
struct wrap
{
std::vector<T> value;
};
typedef typename boost::mpl::inherit_linearly<TL, boost::mpl::inherit<wrap<_2>, _1> >::type Generate;
Generate generated;
public:
void Print()
{
boost::mpl::for_each<TL>(*this);
}
template <typename T>
void operator()(T)
{
std::cout << *static_cast<wrap<T>&>(generated).value.begin() << std::endl;
}
template <typename T>
void Add(T const& t)
{
static_cast<wrap<T>&>(generated).value.push_back(t);
}
};
Here TL is a boost::mpl container of what types should be held.
I think that provides a good starting point for expanding, but covers much of the metaprogramming parts.
I hope this helps others.