After I learned how to pass static function (HashFunction) as a class (Collection<T,HashFunction>) template parameter, I am very addicted to it.
I use it in many places ... now I just realize that if I want to change HashFunction's signature, I will be obliged to modify code in various location.
Example
There are some classes (B and C) that are designed to be used as element of a custom collection (Collection<T,HashFunction>):-
class B{
int bHash;
public: static int& getHash(B& b){return b.bHash;} //#1
//.... other complex thing about B ....
};
class C{
int cHash1;
public: static int& getHash1(C& c){return c.cHash1;} //#2
int cHash2;
public: static int& getHash2(C& c){return c.cHash2;} //#3
//.... other complex thing about C ....
};
//There are about 20 places, i.e. #1 to #20
//They have a thing in common : return an integer field
The Collection<T,HashFunction> (its code is not shown) works similar as a hashset of T.
Here is the usage:-
Collection<B,&B::getHash> collectB;
Collection<C,&C::getHash1> collectC1;
Collection<C,&C::getHash2> collectC2;
//There are about 30+ locations.
Problem
Signature of the hash function (#1,#2,#3 and inside Collection) may require change in the future.
For example, the signature may change from
int bHash;
static int& getHash(B& b){return b.bHash;}
to
HashStructure bHash; //"HashStructure" is a new class
static HashStructure& getHash(B& b,int notUsed){return b.bHash;}
//They tend to still have a thing in common : return a "HashStructure" field
//Here is the maximum possible difference :-
HashStructure bHash[3];
static HashStructure& getHash(B& b,int index){return b.bHash[index];}
//They are likely consistent for both B and C.
Changing Collection to use the new signature is not hard, but changing all signature of #1 to #20 is tedious.
This indicates a maintainability problem.
Question
Suppose I can reverse time to when there are only #1 to #3,
how to modify the code/design (in the example) to prevent maintainability problem.
Opinions:
I should use inheritance (A and B derived from a new class),
but it doesn't fit. (Because B can have unlimited amount of hash function. Moreover, the names of hash function are likely different from A's.)
Some certain design pattern might help. (?)
Variadic template and SFINAE might help. (from Danh's comment, thank!)
To prevent the maintainability problem, I would not have used functions as template arguments in the first place. I would have gone for a 1 type == 1 hash function design, similar to what the STL does to solve the same problem.
Whichever reason you have to stick the different hash functions into the same class can be solved using either inheritance or friendship.
This way, only the call sites have to be updated when the signature change. You could also provide both signatures until every call site has been updated, allowing you to update the code base step by step.
Example:
#include <utility>
class C {
static int cHash1;
};
int C::cHash1 = 0;
struct C1 : public C {
static int hash(C &value);
static int hash(C &value,bool);
};
struct C2 : public C {
static int hash(C &value);
static int hash(C &value,bool);
};
template <class Value, class HashFunction>
struct Collection {
using key_type = decltype(HashFunction::hash(std::declval<HashFunction&>()));
};
template <class Value, class HashFunction>
struct CollectionUpdated {
using key_type = decltype(HashFunction::hash(std::declval<HashFunction&>(), std::declval<bool>()));
};
int main() {
Collection<int, C1> c1;
Collection<int, C2> c2;
CollectionUpdated<int, C1> c1_up;
CollectionUpdated<int, C2> c2_up;
return 0;
}
It seems that getHash can be factorized into
template <typename T, int (T::*hash)>
int& getHash(T& t) { return t.*hash; }
Then usage is:
Collection<B, &getHash<B, &B::bHash>> collectB;
Collection<C, &getHash<C, &C::cHash1>> collectC1;
Collection<C, &getHash<C, &C::cHash2>> collectC2;
And later, you can change implementation of getHash once:
template <typename T, int (T::*hash)[3]>
static HashStructure& getHash(T& t, int index) { return (t.*hash)[index]; }
Related
I have a program in which I would like to choose a set of types (from predefined lists) at run time, not compile time.
Below is an example of the kind of code I'd like to run; Even and Log are types to define a numerical grid, and deriv_Ox is a differentiation scheme of order x:
struct Even {
double a, b;
};
struct Log {
double a, x0, b;
};
// ...
struct deriv_O2 {
vec_type operator() (const vec_type & f_points) const;
};
struct deriv_O4 {
vec_type operator() (const vec_type & f_points) const;
};
// ...
template <class grid_type, class deriv_type>
void run_calculation (const std::string param_file) {
auto grid = grid_from_file<grid_type>(param_file);
auto deriv = deriv_from_file<deriv_type>(param_file);
// ...
}
I would like to decide which of these types to use at run time, by reading a parameter file. My solution was to use tags and case statements to decide which type to use from a single list, then nest each case statement in a function deciding each type in the set as follows:
enum struct grid_tag { Even, Log };
enum struct deriv_tag { O4, O2 };
grid_tag grid_tag_from_file (const char file_name[]);
deriv_tag deriv_tag_from_file (const char file_name[]);
template <class deriv_type>
void run_calculation (const grid_tag g,
const std::string param_file) {
switch(g) {
case grid_tag::Even:
run_calculation<Even, deriv_type>(param_file);
break;
case grid_tag::Log:
run_calculation<Log, deriv_type>(param_file);
break;
}
}
void run_calculation (const grid_tag g, const deriv_tag d,
const std::string param_file) {
switch(d) {
case deriv_tag::O4:
run_calculation<deriv_O4>(g, param_file);
break;
case deriv_tag::O2:
run_calculation<deriv_O2>(g, param_file);
break;
}
}
int main (int argc, char * argv[]) {
grid_tag g = grid_tag_from_file(argv[1]);
deriv_tag d = deriv_tag_from_file(argv[1]);
run_calculation(g, d, argv[1]);
}
The problem is that I have a set of ~6 types to choose from lists of size ~10, and these will grow in the future. The solution I have at the moment makes adding new types awkward.
Is this solution the best I'm going to do? Am I being very fussy, or is there a better solution someone can suggest? I have looked at boost::variant (as recommended in similar questions) but I don't think this is really suitable for what I want to do.
As written, this leads to "double dispatch", which is not an easy thing to solve in C++ (see e.g. here: Understanding double dispatch C++).
What might be applicable in this case, instead of having:
template <class grid_type, class deriv_type>
void run_calculation (const std::string param_file) {
auto grid = grid_from_file<grid_type>(param_file);
auto deriv = deriv_from_file<deriv_type>(param_file);
// ...
}
to retrieve the grid/deriv from the file and result in a concrete type, to have instead
void run_calculation (const std::string param_file, grid_tag gtag, deriv_tag dtag) {
auto /*Grid interface*/ grid = grid_from_file(param_file, gtag);
auto /*Deriv interface*/ deriv = deriv_from_file(param_file, dtag);
// ...
}
and using virtual function call on the Grid/Deriv interface to do the stuff.
(if you do not want to pollute the original grid/deriv classes by the virtual methods, you could also create wrappers for them)
The advantage of this (of course if applicable to your actual situation) would be, that you would not need to solve all the combinations. Compared to the "switch" solution (works in a similar way), you do not need to remember to put switches everywhere to decide the types, you can just call the appropriate virtual functions to do the work (and if the virt. functions are pure in the interface, you cannot forget to provide them, because it will not compile otherwise).
Also, instead of grid_tag, deriv_tag, you could provide a virtual method on the interfaces to read from the file appropriately.
And I would also recommend to pass the string by const ref ("const std::string & param_file"), not by value (copies made).
Selecting a type from a runtime value inherently have some ugliness involved, but judging from the snippet provided, a table of functions would work just fine
enum struct grid_tag { Even, Log, size };
enum struct deriv_tag { O4, O2, size };
using calculation = void (*)(std::string);
calculation table[grid_tag::size][deriv_tag::size]; // populate them
void run_calculation (const grid_tag g, const deriv_tag d, const std::string& param_file)
{
table[g][d](param_file);
}
You can solve this creating several interface (abstract virtual classes with no method implemented) , one for each type you want to decide at runtime.
You then can use a template method pattern to write your algorithm using the interfaces you have written.
This way, adding elements to the lists of type is just adding a new class implementing the interface.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I have a lot of subclasses of an abstract class Letter, like A, B, C, D, etc. Letter has an integer ID variable, and every subclass of Letter gets assigned a unique id.
I then have another class, call it Alphabet. Alphabet has an
list<shared_ptr<Letter>>
member. Here is the problem... I would like to elegantly add B's and C's or other subclasses of Letter to particular instances of Alphabets. I think the most convenient way to do this would be to use the integer id of subclass somehow. In other words, I want to be able to have something like Alphabet.addLetter(int id), so if I did alphabet1.add(14), it would somehow add a shared_ptr for class H to the list.
Is there an elegant way to do this, avoiding some huge if statement where that I need to constantly update every time I add or remove one of the B, C, D, E, etc. classes? I'm hoping there's some kind of template-solution, but I'm not very familiar with advanced c++ notions like factories and templates. The naive thing I wanted was some kind of vector/map that converted my ids into class names, so that I could do something like
list.push_back(shared_ptr<classVector(i)>(new classVector(i))
or something like that, though I have no idea if that's possible.
Thanks!
p.s. I just chose the Alphabet example because I didn't want to give unnecessary detail. Obviously I'm not trying to design alphabets in such a silly way, lol.
edit: I'm struggling to make this make sense. My goal is to be able to create new subclasses of Letter very quickly with minimal effort. I would like to avoid having to type out code that looks like...
list.push_back(shared_ptr<X>(...));
every time I make a new letter. Does this make sense at all?
This is pretty hard to follow, but I think what you want is something along the lines of the following:
// where make_unique<> is from C++14 in std:: or like:
template <typename T, typename ... TArgs>
std::unique_ptr<T> make_unique(TArgs &&... args) {
return std::unique_ptr<T>(new T(std::forward<TArgs>(args)...));
}
struct Letter {
virtual ~Letter() { }
virtual void foo() = 0;
};
template <unsigned int N> struct LetterCode; // Note: no default implementation!
struct Alphabet {
// Indexed access, if you'll have 1 of each type max:
std::vector<std::unique_ptr<Letter>> v;
// If you don't need parameters, as mentioned in comments below ...
template <unsigned int N>
void addLetterN() {
if (N > v.size() + 1) { v.resize(N + 1); }
v[N] = make_unique<LetterCode<N>::type>(); // see below ...
}
// If your coding is complete from 0...N, this does the whole shebang.
template <unsigned int N>
void addLettersN() {
addLetters<N - 1>();
addLetterN<N>();
}
template <>
addLettersN<0>() {
addLetterN<0>();
}
};
If you need numeric codes for something like deserialization and never need constructor arguments, you can use a type trait template like follows to statically 'register' the types:
struct B : Letter {
B(int n, bool b, char const *name);
void foo() override;
};
template <> struct LetterCode<2> { using type = B; };
struct C : Letter {
C(double d);
void foo() override;
};
template <> struct LetterCode<3> { using type = C; };
void bar() {
Alphabet a;
a.addLetterN<2>();
a.addLetterN<3>();
// --OR--
a.addLettersN<3>(); // will do 0...3 in one fell swoop.
for (auto &i : a.v) {
if (!i) { continue; } // v is sparse, unlike l
i->foo();
}
If you need generalized constructor argument passing, you can use perfect forwarding, which is designed for cases like this and obviates the need for enum IDs, etc., from older styles of factories:
struct Alphabet {
std::list<std::unique_ptr<Letter>> l;
// variadic factory that chucks new (shared_ptr) objects in the list.
template <typename T, typename ... TArgs>
void addLetter(TArgs && ... args) {
l.push_back(make_unique<T>(std::forward<TArgs>(args)...));
}
};
void baz() {
Alphabet a;
a.addLetter<B>(1, false, "pony");
a.addLetter<C>(2.718281828);
for (auto &i : a.l) {
i->foo(); // can call virtual funcs here all you want ...
}
}
This is relatively easy if I understood you correctly, using what's called a factory-pattern.
If you can list all of the derived types:
Letter header:
struct Letter {
enum LetterEnum {LetterA, LetterB, LetterC, LetterCount};
virtual ~Letter() {} //base types should always have virtual destructor
virtual void foo() = 0;
static std::unique_ptr<Letter> construct(LetterEnum c);
};
Implementation headers:
struct A : Letter {
void foo() override;
};
struct B : Letter {
void foo() override;
};
struct C : Letter {
void foo() override;
};
Letter body:
std::unique_ptr<Letter> Letter::construct(Letter::LetterEnum c)
{
switch(c) {
case Letter::LetterA : return make_unique<A>();
case Letter::LetterB : return make_unique<B>();
case Letter::LetterC : return make_unique<C>();
default: throw ...;
}
}
Usage:
int main() {
char c;
std::cin >> c;
//get a letter of the derived type associated with the letter entered
std::unique_ptr<Letter> ptr = Letter::construct(c);
}
If you can't list all of the derived types:
Allow the derived types to register themselves with the Letter class, and then Letter can use that to create each of the derived types. This way, adding and deleting the derived types involves no changes to any other files. Easy!
struct Letter {
virtual ~Letter() {} //destructor is always virtual when inheretence is involved
....
//this is a "shared" function in the Letter class itself
//it takes a letter, and returns a dynamically allocated instance
//of the derived type corresponding with that letter
static std::unique_ptr<Letter> construct(char c);
//this typedef represents the actual function that returns
//each dynamically allocated derived type
typedef std::function<std::unique_ptr<Letter>()> letter_ctor;
//this is a "shared" function in the Letter class itself
//it takes a letter, and a function that creates derived types,
//and saves them inside the container ctors
static bool register(char c, letter_ctor func);
private:
//this is a "shared" member in the Letter class.
//There is only one shared by all of the Letters. Like a global.
//When you give it a letter, it gives you a function.
//and is VERY fast for large numbers of entries
static std::unordered_set<char,letter_ctor> ctors;
};
and in your implementation file:
//here's the function that derived types register themselves with
//pretty straightforward, just inserts the pair into the unordered_map
bool Letter::register(char c, Letter::letter_ctor func)
{return Letter::ctors.insert(std::make_pair(c,std::move(func))).second;}
//and here's the function that creates the derived types
//it checks if the letter is in the unordered_map
//if the letter isn't there, it throws an exception
//otherwise, it calls the function associated with that letter
//which creates the derived type on the heap, and returns a pointer to it
std::unique_ptr<Letter> Letter::construct(char c)
{
auto it = Letter::ctors.find(c);
if (it == Letter::ctors.end())
throw ...;
return it->second(); //construct that letter
}
and then your derived types do this:
//you know this part
struct LetterA : public Letter
{
....
};
//derived types have to register themselves:
//this is a global, so when the program loads, it automatically calls this
//even before main runs*
//it registers the letter 'A' and a function that creates a LetterA class on the heap
static bool registerA = Letter::register('A', [](){return make_unique<LetterA>();});
and then you can easily create arbirary derived types!
int main() {
char c;
std::cin >> c;
//get a letter of the derived type associated with the letter entered
std::unique_ptr<Letter> ptr = Letter::construct(c);
}
*It doesn't always get called before main. If you have problems, put an bool init_A(); in the A header, and bool init_A(){return true;} in the A implementation file, and in your main file have static bool AInit=init_A(); which should force it. This is almost never needed in practice though.
As a side note, these depend on having a make_unique, which should have been in C++11, but was left out due to oversight. It will be in C++14. In the meantime, use this:
template<class T, class...Us>
std::unique_ptr<T> make_unique(Us&&...us)
{return std::unique_ptr<T>(new T(std::forward<Us>(us)...));}
My understanding is that you want to create a instance of one of the classes, dependend on an id which relates to the class from which an instance should be created.
If so, please have a look for factory pattern. There are a lot of factory implementations, also based on template recursive expansion of a typelist.
Pseudo Code:
Factory<A,B,C,D> fac; // the list must be changed, if some more classes comes and goes
id_type id;
list<base> l;
l.push_back=fac.Create(id);
It is also quite simple to implement such a class yourself.
The goal is simple: create the function factories that returns an array of Alphabet makers.
The index of the letter and the index into the array will be the same.
Ideally, we want to auto-generate said index without having to manually set it.
#include <memory>
#include <vector>
#include <iostream>
template<class T>using Type=T;
template<class...Ts>struct types:std::integral_constant<unsigned,sizeof...(Ts)>
{typedef types type;};
template<class T,class types>struct index_of;
template<class T,class T0, class...Ts>struct index_of<T,types<T0,Ts...>>:
std::integral_constant<unsigned,index_of<T,types<Ts...>>::value+1>
{};
template<class T,class...Ts>struct index_of<T,types<T,Ts...>>:
std::integral_constant<unsigned,0>
{};
template<unsigned,class types>struct type_at;
template<unsigned N, class T,class...Ts>struct type_at<N,types<T,Ts...>>:
type_at<N-1,types<Ts...>> {};
template<class T,class...Ts>struct type_at<0,types<T,Ts...>>{
typedef T type;
};
template<unsigned N,class types>
using type_at_t=typename type_at<N,types>::type;
template<template<class>class Target,unsigned N,class types>
struct nth_apply;
template<template<class>class Target,unsigned N,class...Ts>
struct nth_apply<Target,N,types<Ts...>>{
typedef Target<type_at_t<N,types<Ts...>>> type;
};
template<template<class>class Target,unsigned N,class types>
using nth_apply_t=typename nth_apply<Target,N,types>::type;
This is the type that produces the function pointers for us:
template<class T>struct shared_maker{
template<class...Args>
std::shared_ptr<T> operator()(Args&&...args)const{
return std::make_shared<T>(std::forward<Args>(args)...);
}
template<class R, class... Args>
operator Type<R(Args...)>*() const{
return [](Args... args)->R{
return shared_maker{}(std::forward<Args>(args)...);
};
}
};
Here is what we do for the actual letter types. We forward declare them:
struct A; struct B; // etc
Stick them into a list of types:
typedef types<A,B> Alphabet_Types;
Now, our simple test Alphabet type:
struct Alphabet {
virtual unsigned get_index() const = 0;
};
And a CRTP helper that gets the index of the letter from its offset into the list of types! The virtual get_indexes is just for debugging:
template<class D>
struct Letter:Alphabet{
static const unsigned index = index_of<D, Alphabet_Types>::value;
virtual unsigned get_index() const override { return index; }
};
Now the signature of our array-producer:
typedef std::shared_ptr<Alphabet> spAlphabet;
std::array<spAlphabet(*)(), Alphabet_Types::value> factories();
Here is how we define our (toy) letter classes:
struct A:Letter<A>{};
struct B:Letter<B>{};
ie, use Letter<> as a CRTP base instead of Alphabet.
The only thing left is to write the function factories.
Index boilerplate. C++1y has a replacement:
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...>{};
The actual implementation via a helper function. We get a pack of indexes and expand it, building our std::array of function pointers from our shared_maker above instantiated with an indexed type from the Alphabet_Types we wrote above:
template<unsigned...Is>
std::array<spAlphabet(*)(), Alphabet_Types::value> factories(indexes<Is...>){
return {nth_apply_t<shared_maker,Is,Alphabet_Types>{}...};
}
The actual factories function just forwards to the above helper:
std::array<spAlphabet(*)(), Alphabet_Types::value> factories(){
return factories(make_indexes<Alphabet_Types::value>{});
}
And some trivial test code:
int main() {
std::vector<spAlphabet> vec;
auto builders = factories();
for (int i = 0; i < 2; ++i) {
vec.push_back(builders[i]());
}
for( auto&& ptr:vec ) {
std::cout << ptr->get_index() << "\n";
}
}
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>&
}
What I am needing can be done by storing this pointer of enclosing class into nested class for example this way:
class CEnclosing {
public:
class CNested : public CSomeGeneric {
public:
CNested(CEnclosing* e) : m_e(e) {}
virtual void operator=(int i) { m_e->SomeMethod(i); }
CEnclosing* m_e;
};
CNested nested;
CEnclosing() : nested(this) {}
virtual void SomeMethod(int i);
};
int main()
{
CEnclosing e;
e.nested = 123;
return 0;
}
This works well, but requires sizeof(void*) bytes of memory more for each nested member class. Exist effective and portable way to do this without need to store pointer to instance of CEnclosing in m_e?
As stated previously, C++ does not provide any way to do this. A nested class has no special way to find its enclosing class. The solution you already have is the recommended way.
If you have an advanced scenario, and if you are prepared to maintain non-portable code, and if the cost of storing an additional pointer is important enough to use a risky solution, then there is a way based on the C++ object model. With a number of provisos I won't go into, you can rely on the enclosing and nested classes being laid out in memory in a predictable order, and there being a fixed offset between the start of the enclosing and nested classes.
The code is something like:
CEnclosing e;
int offset = (char*)&e.nested - (char*)&e;
//... inside nested class
CEnclosing* pencl = (CEnclosing*)((char*)this - offset);
OTOH it's equally possible that the offsetof macro may just do it for you, but I haven't tried it.
If you really want to do this, read about trivially copyable and standard layout in the standard.
I believe the following could be portable; though it is not fool-proof. Specifically, it will not work across virtual inheritance.
Also, I would like to point that it is not safe, in that it will happily compile even if the member you pass does not correspond to the one you compute the offset with:
#include <iostream>
template <typename C, typename T>
std::ptrdiff_t offsetof_impl(T C::* ptr) {
C c; // only works for default constructible classes
T* t = &(c.*ptr);
return reinterpret_cast<char*>(&c) - reinterpret_cast<char*>(t);
}
template <typename C, typename T, T C::* Ptr>
std::ptrdiff_t offsetof() {
static std::ptrdiff_t const Offset = offsetof_impl(Ptr);
return Offset;
}
template <typename C, typename T, T C::* Ptr>
C& get_enclosing(T& t) {
return *reinterpret_cast<C*>(reinterpret_cast<char*>(&t)
+ offsetof<C, T, Ptr>());
}
// Demo
struct E { int i; int j; };
int main() {
E e = { 3, 4 };
//
// BEWARE: get_enclosing<E, int, &E::j>(e.i); compiles ERRONEOUSLY too.
// ^ != ^
//
E& ref = get_enclosing<E, int, &E::j>(e.j);
std::cout << (void const*)&e << " " << (void const*)&ref << "\n";
return 0;
}
Still, it does run on this simplistic example, which allowed me to find 2 bugs in my initial implementation (already). Handle with caution.
The clear and simple answer to your question is no, C++11 doesn't have any special feature to handle your scenario. But there is a trick in C++ to allow you to do this:
If CEnclosing didn't have a virtual function, a pointer to nested would have the same value as a pointer to the containing instance. That is:
(void*)&e == (void*)&e.nested
This is because the variable nested is the first in the class CEnclosing.
However, since you have a virtual function in CEnclosing class, then all you need to do is subtract the vtable size from &e.nested and you should have a pointer to e. Don't forget to cast correctly, though!
EDIT: As Stephane Rolland said, this is a dangerous solution and, honestly, I wouldn't use it, but this is the only way (or trick) I could think of to access the enclosing class from a nested class. Personally, I would probably try to redesign the relation between these two classes if I really want to optimise memory usage up to the level you mentioned.
How about using multiple inheritance like this:
class CNested {
public:
virtual void operator=(int i) { SomeMethod(i); }
virtual void SomeMethod(int i) = 0;
};
class CEnclosing: public CSomeGeneric, public CNested {
int nEncMember;
public:
CNested& nested;
CEnclosing() : nested(*this), nEncMember(456) {}
virtual void SomeMethod(int i) { std:cout << i + nEncMember; }
};
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).