C++ creating variations of classes with different combinations of fields - c++

templates allow in c++ to automatically create a lot of classes with the same interface, but different data stored.
i'm looking for something similar (i don't know whether it exists, that's why I ask here) that automatically creates for me variations of an object storing only a subset of the datamembers.
let's say i have a
class FullClass
{
public:
bool A;
int B;
float C;
double D;
};
then i would like to have all possible combinations of those fields like for example:
class BDClass
{
public:
int B;
double D;
};
or
class BCDClass
{
public:
int B;
float C;
double D;
};
and i want to be able to cast from any of the variation classes to FullClass such that the defined fields will be copied, and the missing fields are set to defaultvalues:
FullClass foo;
BDClass bar = BDClass(3, 5.0);
foo = (FullClass) bar;
Is there any mechanism that let's the compiler create those variations for me, or do I have to define all possible combinations myself?
thanks!
edit:
why am I looking for this?
I have a software construct that follows the strategy pattern. thus, i have a bunch of different algorithms (more than 30) using the same interface. the client shall be able to use this interface without knowing what exact algorithm currently is running behind. the client calculates such a 'FullClass' object and passes it through the interface - however, each algorithm uses only a subset of the fields provided in this object (and each algorithm uses different ones).
This strategy-pattern construct is fixed and i cannot change it.
Now i want to 'record' the sequence of such generated 'FullClass' objects, such that the complete flow of the usage of this construct can be repeated without having to recalculate those 'FullClass' objects. However, this is a lot of data (which i'd like to keep in mainmemory for performance reasons) and since most of the algorithms only use a small subset of the fields, i only want to store the fields which are effectively used

I cannot even imagine why do you need this, but you can try use mixins:
class Dummy
{
};
<template Base>
class AClass : public Base
{
public:
bool A;
};
<template Base>
class BClass : public Base
{
public:
int B;
};
... //( etc)
BClass< AClass<Dummy>> abClass;
abClass.B = 4;
abClass.A = false;
And if you will keep going you will be able to do:
DClass< CCLass< BClass< AClass<Dummy>>>> abcdClass;

I might be wrong or it might be an non-efficient solution to your problem, but maybe using tuple will solve it : http://www.boost.org/doc/libs/1_41_0/libs/tuple/doc/tuple_users_guide.html
That said, you should explain the problem you're trying to solve, as Neil said. Why would you need this.

First, you can define four classes for each data type, then declare templae class for type pairs, then for three-type combinations, then for four ones. You can't get it any simpler than that.

I think you could do something using the private class data pattern, and then some terrible memcopy tricks:
class Full
{
private:
struct fullData
{
a;
b;
c;
d;
e;
...
z;
} * m_pData;
public:
Stuff!
}
class Partial
{
private:
struct partialData
{
a;
b;
c_filler; //This is an issue
d;
}
public:
Different Stuff!;
}
Then, when you copy, just literally copy the memory of partialData into fullData, filling the rest of fullData with zeros.
The issues are that this only works with datatypes that don't need you to use their constructors (so, there's no safety checks in here), and you have to put in padding (as above) to make sure your data lines up properly.
But your copy-constructor gets to be a memcopy then a memfill;
(note, I almost certainly have the memcopy and fill syntax wrong)
template<class T>
Full(T& t)
{
m_pData = new fullData;
memcopy(/*to*/m_pData, /*from*/Partial->getData(), /*how much to copy*/ sizeof(T));
memfill(/*tp*/m_pData, /*how much to copy*/ sizeof(fullData) - sizeof(T), /*with*/ 0);
}
May work for your particular situation, but it's not particularly safe or pretty.

Have you considered just writing a preprocessor to codegen what you need?

I personally really appreciate Boost.Fusion ;)
Here, I would use boost::fusion::map since it allows to mix types quite easily.
You need to use a combination of tags types (types only used for compilation purpose) and of real types, used to store data.
Let's define our tags:
class a_tag { typedef bool type; };
class b_tag { typedef int type; };
class c_tag { typedef float type; };
class d_tag { typedef double type; };
Then you can write a macro using Boost.Preprocessor which takes the list of tags and generates the appropriate boost::fusion::map
GENERATE_MY_TYPE(TypeName, (a_tag)(b_tag)(c_tag)(d_tag));
// For information: (a_tag)(b_tag)(c_tag)(d_tag) is called a sequence in PP
The type shall be something like:
typedef boost::fusion::map<
std::pair<a_tag, a_tag::type>,
std::pair<b_tag, b_tag::type>,
std::pair<c_tag, c_tag::type>,
std::pair<d_tag, d_tag::type>
> TypeName;
Or more likely a wrapper using the boost::fusion::map as an implementation detail, say:
// defined once
template <class Vector>
struct TemplateType
{
typedef Vector tags_type;
typedef detail::deduce<Vector>::type data_type
// which for Vector = boost::mpl::vector<a_tag, b_tag, c_tag, d_tag> should be
// typedef boost::fusion::map<
// std::pair<a_tag, a_tag::type>,
// std::pair<b_tag, b_tag::type>,
// std::pair<c_tag, c_tag::type>,
// std::pair<d_tag, d_tag::type>
// > data_type;
data_type m_data;
template <class T>
boost::fusion::result_of::at<T, data_type> at()
{
return boost::fusion::at<T>(m_data);
}
};
// Generated by the macro, filling boost::mpl::vector by iteration
// the sequence
typedef TemplateType< boost::mpl::vector<a_tag, b_tag, c_tag, d_tag> > TypeName;
And then you only need the type defined to provide a conversion trick from a subset of tags. This might be defined only once if you need only have the full subset.
template <class Vector>
TypeName toTypeName(TemplateType<Vector> const& arg)
{
TypeName result;
result.fill(arg);
return result;
}
With fill being defined as:
namespace detail
{
class NoAssign
{
template <class Pair, class TT> static Do(Pair const&, TTconst&) { }
};
class Assign
{
template <class Pair, class TT>
static Do(Pair& p, TTconst& tt)
{
p.second = tt.at<typename Pair::first_type>();
};
};
template <class Vector>
class Filler
{
public:
Filler(TemplateType<Vector> const& ref): m_ref(ref) {}
template <class T, class U>
void operator()(std::pair<T,U>& p) const
{
typedef typename boost::mpl::find<T,Vector>::type it;
typedef typename boost::mpl::end<Vector>::type end;
typedef typename boost::mpl::if< boost::same_type<it,end>, NoAssign, Assign> assign;
assign::Do(p, m_ref);
}
private:
TemplateType<Vector> const& m_ref;
};
}
template <class Vector>
template <class OV>
void TemplateType<Vector>::fill<OV>(TemplateType<OV> const& rhs)
{
boost::fusion::for_each(m_data, detail::Filler<OV>(rhs));
}
I love those problems, but of course being forced to use both Meta Template Progamming AND Preprocessing to generate some template classes / methods... means some lengthy solutions and some headaches. Once done however the syntax can be really neat (for the user).

Related

How to automate creation of tuples of template classes based on elements of an array?

I have an std::array that is filled with all the types of an enumeration. I'd like to implement my tuples based
on this.
class CompBase
{
public:
enum CompType{
INPUT,
GRAPHICS
// ( + 5-10 additional types)
};
static const std::array<CompType, 2> compTypeArr;
};
const std::array<CompBase::CompType, 2> CompBase::compTypeArr =
{
CompBase::INPUT,
CompBase::GRAPHICS
};
template<CompBase::CompType compType_e>
class CompHolder {}; // owns one component
template<CompBase::CompType compType_e>
class CompContainer {}; // references N components
class CompInterface
{
// ...
private:
std::tuple // I want to automate this,
<
CompHolder<CompBase::INPUT>,
CompHolder<CompBase::GRAPHICS>
> compHolders;
};
class CompHandler
{
// ...
private:
std::tuple // and this process, based on the predefined array
<
CompCont<CompBase::INPUT>,
CompCont<CompBase::GRAPHICS>
> compContainers;
};
To my understanding std::make_tuple is not even constexpr before c++14 ref
so I'm not sure if this is possible at all since I'd need a c++11 method. The presence of the array is I think sort of mandatory because an enumeration alone doesn't provide the necessary functionality for something like this.
Here's a solution that works in C++11. As discussed in the comments, using an std::array would work in C++14, where its const accessors were made constexpr.
#include <tuple>
#include <type_traits>
#include <iostream>
class CompBase
{
public:
enum CompType {
INPUT,
GRAPHICS
// ( + 5-10 additional types)
};
};
template<CompBase::CompType...> struct CTLHelper;
using CompTypeList = CTLHelper<
CompBase::INPUT,
CompBase::GRAPHICS
>;
template<template<CompBase::CompType> class, class> struct CompTupleMaker;
template<template<CompBase::CompType> class H, CompBase::CompType... Es>
struct CompTupleMaker<H, CTLHelper<Es...>>
{
using type = std::tuple<H<Es>...>;
};
template<CompBase::CompType compType_e>
class CompHolder {}; // owns one component
template<CompBase::CompType compType_e>
class CompContainer {}; // references N components
using CompHolderTuple = CompTupleMaker<CompHolder, CompTypeList>::type;
using CompContainerTuple = CompTupleMaker<CompContainer, CompTypeList>::type;
class CompInterface
{
// ...
private:
CompHolderTuple compHolders;
};
class CompHandler
{
// ...
private:
CompContainerTuple compContainers;
};
int main()
{
// just a quick check
std::cout << std::is_same<CompHolderTuple, std::tuple<CompHolder<CompBase::INPUT>, CompHolder<CompBase::GRAPHICS>>>::value << '\n';
}
If you really need those enumerators in an array in C++11, you could use a built-in array declared constexpr - you can reference its elements in constant expressions. I'd say that only makes sense if you need the array for something else as well; if all you need is a holder for the list of enumerators, the variadic solution is simpler in this case. For the array solution, you'd need something similar to C++14's std::index_sequence to expand the array.

I need a non template solution

I have a class defined like this
class A
{
private:
map<int,vector<int>> m;
public:
vector<int> GetJsonVal(int k)
{
return m[k];
}
};
I would like to change it into something like this
template<class T>
class A
{
private:
map<int,T> m;
public:
T GetJsonVal(int k)
{
return m[k];
}
};
However, I have many other places that plainly use only type A, so if I change my class into the latter, I have to fix a lot i.e change all into A<type>, which I don't want. In those places I simply do void func(A*p) or A& r=....
So, how can I both use i.e A<float> and A anywhere I like ?
So, the easiest and most legible solution that comes to mind is a type alias:
template <typename T>
class Tool {
private:
map<int,vector<T>> m;
public:
vector<T> GetJsonVal(int k) {
return m[k];
}
};
using A = Tool<int>;
And so now the old code can continue using A, and all new code can use Tool<int> or another type alias.
You could use type-erasue, but will still need to update the code here and there... An approach could be doing something like:
class A {
map<int, boost::any> m;
template <typename T>
T valueAs(int idx);
};
A a;
a.valueAs<int>();
You would have the implementation verify that the type stored and the type retrieved are the same. Then you would probably want to go to all existing uses of A and enforce the check (or check the potential error).
That is, if you want to support mixed types inside A... if you each A can only hold a particular type, you can just make a ATmpl type with the contents in the question, and then typedef ATmpl<vector<int>> A;. At this point you would still have to fix some use cases (specifically: forward declarations)...
Use template class specialization, I would say
template <> class A<vector<int>>
{
// all your old code here
}
should work...
UPDATE
Just to be clear, there is a semantic difference between template specialization and type alias. With template specialization you could put your (true and tested and bug-for-bug compatible) code into specialization and use new and shiny (but potentially buggy code) elsewhere in new production, and later when you fill it is good enough you could remove specialization and use only new code. With type specialization it is new code everywhere right away...

How to induce some template classes being united by one template?

I have some template classes. They are united by one namespace, and really they depends on each other's template parameter.
That is a good point for using #define T instead of template, and use in all classes, but client for those classes may want create some such pairs with different T, that is why I want to use templates.
But if I create just two separated classes with their own separated templates, I have good chance that client will make mistake and will put different values there. So, I would like to avoid it, if it is possible, to make set T once for pair of such classes and use both classes with it's value.
I would like to create something like that (just imagine):
template<int T>
namespace Sample
{
struct A
{
char _data[T];
}
struct B
{
void Get(A& a)
{
memcpy(b, a._data, T);
}
char b[T];
}
}
So, there are separated classes, but if one has parameter T = 50, then other have to work with same parameter. Best solution - template namespace, but C++ has no template namespaces.
Is it possible to make it somehow? Maybe I need any pattern?
I don't want to add something like:
char X1[T1 - T2 + 1];
char X2[T2 - T1 + 1];
Inside class B, to get error if T1 != T2 at compilation, I would like to find simple and beauty solution for that task, I believe it have to exist :-)
Use nested classes. Simply replace namespace with struct.
template<int T>
struct Sample {
struct A {
char _data[T];
};
struct B{
// ...
};
// You can have static methods that operate on types from
// the same template instance without specifying the type
static void foo(B& b) {
A a{0};
b.Get(a);
}
};
int main() {
Sample<2>::A a{0};
Sample<2>::B b;
b.Get(a);
}
Perhaps remove the constructor of Sample so no one tries to instantiate it.
I don't see how this is a problem. The following code already will not compile due to different values being used for the respective T parameters:
template <int T>
struct A
{
};
template <int T>
struct B
{
Get(A<T>& a) {}
};
int main()
{
A<5> a;
B<10> b;
b.Get(a); // cannot convert A<5> to A<10>&
}

Runtime value to type mapping

I've got a list of types which can be send over the network, take this example:
enum types {
E_T1,
E_T2,
E_T3,
E_T4
};
Now I have a list of classes which correspond to each of the types, let's say each is declared as class E_T1 {...}, class E_T2 {...}, etc.
They are not derived from a common base class and it's not possible to do so. Each of the classes has a verification method I need to invoke with the data send over the network. The client sends the data D and a id correspointing to the message type. I need to get hold of the object corresponding to the type. I can use C++0x features if needed.
What I've tried so far is using specialized templates for the types, holding a typedef for the object related to it. This was obviously a stupid idea as templates parameters need to be compile time constant so doing something along getType<data.id()>::type is not possible.
Then I tried using Boost.Variant to get a common returnable type like this (used mpl vector to iterate over the registered types at runntime for debbuging):
template <typename C>
struct getType() {
typedef C type;
}
typedef boost::mpl::vector<
getType<E_T1>,
getType<E_T2>,
getType<E_TX>...
> _types;
typedef boost::make_variant_over<_types>::type _type;
//use a map to store each type <-> id
boost::unorderd_map<types, _type> m;
m[E_T1] = getType<E_T1>();
m[data.id()]::type x; //<- access type, can now call x.validate(data)
The problem with this is that it's limited to 20 entries per variant per default. This can be overwritten but from what I understood the overhead per type should be considered and we are talking about a few thousand types here.
Also tried boost.any but it doesn't hold any type information so that's out of the question again. Has anyone any good ideas how this can be solved elegantly?
Looking for something where I don't have to write a 1k switch statement anytime I handle a type.
All types are nown at compile type, same goes for their corresponding IDs.
Id -> Type resolving needs to happen at runtime though.
Thanks in advance,
Robin.
External Polymorphism (*)
It's a widely known idiom, however it's widely used: I first encountered it in the shared_ptr implementation and it's been quite useful in my toolbox.
The idea is to actually create a base class for all those types. But not having them derive from it directly.
class Holder {
public:
virtual ~Holder() {}
virtual void verify(unsigned char const* bytes, size_t size) const = 0;
}; // class Holder
template <typename T>
class HolderT: public Holder {
public:
HolderT(): _t() {}
virtual void verify(unsigned char const* bytes, size_t size) const {
_t.verify();
}
private:
T _t;
}; // class HolderT
template <typename T>
std::unique_ptr<Holder> make_holder() {
return std::unique_ptr<Holder>(new HolderT<T>());
}
So, it's the classic strategy of adding a new level of indirection.
Now, you obviously do need a switch to move from value to class. Or perhaps... a map ?
using maker = std::unique_ptr<Holder> (&)();
using maker_map = std::unordered_map<types, maker>;
std::unique_ptr<Holder> select(types const E) {
static maker_map mm;
if (mm.empty()) {
mm.insert(std::make_pair(E_T1, make_holder<EC_T1>));
// ...
}
maker_map::const_iterator it = mm.find(E);
if (it == mm.end()) { return std::unique_ptr<Holder>(); }
return (*it->second)();
}
And now you can handle them polymorphically:
void verify(types const E, unsigned char const* bytes, size_t size) {
std::unique_ptr<Holder> holder = select(E);
if (not holder) { std::cerr << "Unknown type " << (int)E << "\n"; return; }
holder->verify(bytes, size);
}
Of course, you're welcome to make the strategy vary according to your needs. For example moving the map out of select so that you can register your types dynamically (like for plugins).
(*) At least that's the name I have for it, I would quite happy to find out it's already been named.
I'll assume you have a generic way of handling a message, such as for example an overloaded function:
void handle_message(const E_T1& msg);
void handle_message(const E_T2& msg);
//...
Now, you do not really need to get the object's type. All you need is a way to handle a message of that type, given the undecoded message.
So, I recommend you populate a map of factory functions:
std::unordered_map<types, std::function<void (unsigned char const* bytes, size_t size)> handlers;
handlers[E_E1] = [](unsigned char const* bytes, size_t size) { handle_message(E_T1(bytes, size)); };
// ...
Then, once you've decoded the type, you can use handlers[type](bytes, size) to decode and handle a message.
Try variadic templates and your already defined getType class:
enum types { T1_ID, T2_ID, .... };
class T1; class T2; class T3; ....
template <types t> struct getType;
template <> struct getType<T1_ID> { typedef T1 type; };
template <> struct getType<T2_ID> { typedef T2 type; };
...
And the operation verify:
template <types...>
struct type_operation;
template <types t1, types... rest>
struct type_operation<t1, rest...>
{
void verify(types t)
{
if (t == t1)
{
typename getType<t1>::type a;
a.verify(); // read from network and verify the rest of data....
}
else type_operation<rest...>::verify(t, data);
}
};
template <>
struct type_operation<>
{
void verify(types t)
{
ostringstream log; log << "not suppoted: " << t;
throw std::runtime_error(log.str()); //
}
};
Usage:
typedef type_operation<T1_ID, T2_ID, T3_ID, ,,.., TN_ID> type_mapping;
types id;
readFromNetwork(id);
type_mapping::verify(id);

Generic container for multiple data types in C++

Using C++, I'm trying to create a generic container class to handle multiple data types. It's a common problem with a variety of solutions, but I've found nothing as... intuitive as I've grown accustomed to in languages like Python or even VB/VBA...
So here's my scenario:
I've built a DataContainer class based on boost::any which I use to store multiple data types of multiple elements. I use a map declared as:
std::map<std::string, DataContainer* (or DataContainerBase*)>
where DataContainer is a class that encapsulates an object of the type:
std::list<boost::any>
along with convenience functions for managing / accessing the list.
However, in the end, I'm still forced to do type conversions outside the data container.
For example, if I were to store a list of int values in the map, accessing them would require:
int value = boost::any_cast<int>(map["myValue"]->get());
I'd rather the boost code be contained entirely within the data container structure, so I would only need type:
int value = map["myValue"]->get();
or, worst-case:
int value = map["myValue"]->get<int>();
Of course, I could enumerate my data types and do something like:
int value = map["myValue"]->get( TYPE_INT );
or write type-specific get() functions:
getInt(), getString(), getBool() ...
The problem with the last two options is that they are somewhat inflexible, requiring me to declare explicitly each type I wish to store in the container. The any_cast solution (which I have implemented and works) I suppose is fine, it's just... inelegant? I dunno. It seems I shouldn't need to employ the internal mechanics externally as well.
As I see it, passing the value without declaring the value type in the call to the DataContainer member function would require a void* solution (which is undesirable for obvious reasons), and using a "get()" call would require (so far as I can tell) a "virtual template" member function defined at the base class level, which, of course, isn't allowed.
As it is, I have a workable solution, and really, my use in this case is limited enough in scope that most any solutions will work well. But I am wondering if perhaps there's a more flexible way to manage a generic, multi-type data container than this.
If you want to introduce some sugar for this:
int value = boost::any_cast<int>(map["myValue"]->get());
then you might want to make the get() function to return a proxy object, defined +- like this:
struct Proxy {
boost::any& value;
Proxy(boost::any& value) : value(value) {}
template<typename T>
operator T() {
return boost::any_cast<T>(value);
}
};
Then this syntax would work:
int value = map["myValue"]->get();
// returns a proxy which gets converted by any_cast<int>
However I recommend to keep things explicit and just use that syntax:
int value = map["myValue"]->get<int>();
Here get doesn't return a proxy object with a template method, but is a template method itself (but does the same as the template conversion operator shown above).
Today I have done some source code for the purpose you want. I know that this question is so old, but maybe this little piece of code is helpful for someone. It is mainly based on boost:any.
/*
* AnyValueMap.hpp
*
* Created on: Jun 3, 2013
* Author: alvaro
*/
#ifndef ANYVALUEMAP_HPP_
#define ANYVALUEMAP_HPP_
#include <map>
#include <boost/any.hpp>
using namespace std;
template <class T>
class AnyValueMap {
public:
AnyValueMap(){}
virtual ~AnyValueMap(){}
private:
map<T, boost::any> container_;
typedef typename map<T, boost::any>::iterator map_iterator;
typedef typename map<T, boost::any>::const_iterator map_const_iterator;
public:
bool containsKey(const T key) const
{
return container_.find(key) != container_.end();
}
bool remove(const T key)
{
map_iterator it = container_.find(key);
if(it != container_.end())
{
container_.erase(it);
return true;
}
return false;
}
template <class V>
V getValue(const T key, const V defaultValue) const
{
map_const_iterator it = container_.find(key);
if(it != container_.end())
{
return boost::any_cast<V>(it->second);
}
return defaultValue;
}
template <class V>
V getValue(const T key) const
{
return boost::any_cast<V>(container_.at(key));
}
template <class V>
void setValue(const T key, const V value)
{
container_[key] = value;
}
};
#endif /* ANYVALUEMAP_HPP_ */
A simple usage example:
AnyValueMap<unsigned long> myMap;
myMap.setValue<double>(365, 1254.33);
myMap.setValue<int>(366, 55);
double storedDoubleValue = myMap.getValue<double>(365);
int storedIntValue = myMap.getValue<int>(366);