C++ class member variable knowing its own offset - c++

Is it possible to have a member variable, that would be able to calculate pointer to the containing object from pointer to itself (in it's method)?
Let's have a foreign call interface wrapped in API like this:
template <typename Class, MethodId Id, typename Signature>
class MethodProxy;
template <typename Class, MethodId Id, typename ReturnT, typename Arg1T>
class MethodProxy<Class, Id, ReturnT ()(Arg1T) {
public:
ReturnT operator()(Class &invocant, Arg1T arg1);
};
and similarly for other numbers of arguments from 0 to N. For each class on the foreign side, one C++ class is declared with some traits and this template uses those traits (and more traits for argument types) to find and invoke the foreign method. This can be used like:
Foo foo;
MethodProxy<Foo, barId, void ()(int)> bar;
bar(foo, 5);
Now what I would like to do is define Foo in such way, that I can call like:
Foo foo;
foo.bar(5);
without repeating the signature multiple times. (obviously creating a static member and wrapping the call in a method is simple, right). Well, in fact, that's still easy:
template <typename Class, MethodId Id, typename Signature>
class MethodMember;
template <typename Class, MethodId Id, typename ReturnT, typename Arg1T>
class MethodMember<Class, Id, ReturnT ()(Arg1T) {
MethodProxy<Class, Id, Signature> method;
Class &owner;
public:
MethodMember(Class &owner) : owner(owner) {}
ReturnT operator()(Arg1T arg1) { return method(owner, arg1); }
};
That however means the object will end up containing many copies of pointer to itself. So I am looking for a way to make these instances being able to calculate the owner pointer from this and some additional template arguments.
I was thinking along the lines of
template <typename Class, size_t Offset, ...>
class Member {
Class *owner() {
return reinterpret_cast<Class *>(
reinterpret_cast<char *>(this) - Offset);
}
...
};
class Foo {
Member<Foo, offsetof(Foo, member), ...> member;
...
};
but this complains that Foo is incomplete type at the point.
Yes, I know offsetof is supposed to only work for "POD" types, but in practice for any non-virtual member, which this will be, works. I have similarly tried to pass pointer-to-(that)-member (using dummy base-class) in that argument, but that does not work either.
Note, that if this worked, it could also be used to implement C#-like properties delegating to methods of the containing class.
I know how to do the wrapper methods mentioned above with boost.preprocessor, but the argument lists would have to be specified in a weird form. I know how to write macro to generate generic wrappers via templates, but that would probably give poor diagnostics. It would also be trivial if the calls could look like foo.bar()(5). But I'd like to know whether some clever trick would be possible (plus only such clever trick would probably be usable for properties too).
Note: The member type can't be actually specialized on either member pointer to it nor it's offset, because the type must be known before that offset can be assigned. That's because the type can affect required alignment (consider explicit/parcial specialization).

Asking a question is the best way to realize the answer, so this is where I've got:
The offset can't be a template argument, because the type has to be known before the offset can be calculated. So it has to be returned by a function of the argument. Let's add a tag type (dummy struct) and either a put an overloaded function into Owner or directly into the tag. That way we can define everything we need on one place (using a macro). The following code compiles fine with gcc 4.4.5 and prints correct pointer for all members:
#include <cstddef>
#include <iostream>
using namespace std;
(just preamble to make it really compile)
template <typename Owner, typename Tag>
struct offset_aware
{
Owner *owner()
{
return reinterpret_cast<Owner *>(
reinterpret_cast<char *>(this) - Tag::offset());
}
};
This is what's needed to make the object aware of it's own offset. Property or functor or some other code can be added freely to make it useful. Now we need to declare some extra stuff along with the member itself, so let's define this macro:
#define OFFSET_AWARE(Owner, name) \
struct name ## _tag { \
static ptrdiff_t offset() { \
return offsetof(Owner, name); \
} \
}; \
offset_aware<Owner, name ## _tag> name
This defines structure as the tag and puts in a function returning the required offset. Than it defines the data member itself.
Note, that the member needs to be public as defined here, but we could easily add a 'friend' declaration for the tag support protected and private properties. Now let's use it.
struct foo
{
int x;
OFFSET_AWARE(foo, a);
OFFSET_AWARE(foo, b);
OFFSET_AWARE(foo, c);
int y;
};
Simple, isn't it?
int main()
{
foo f;
cout << "foo f = " << &f << endl
<< "f.a: owner = " << f.a.owner() << endl
<< "f.b: owner = " << f.b.owner() << endl
<< "f.c: owner = " << f.c.owner() << endl;
return 0;
}
This prints the same pointer value on all lines. C++ standard does not allow members to have 0 size, but they will only have the size of their actual content or 1 byte if they are otherwise empty compared to 4 or 8 (depending on platform) bytes for a pointer.

1) There's a gcc extension which seemed fitting:
enum{ d_y = __builtin_choose_expr(N,offsetof(X,y),0) };
But it didn't work as expected, even though manual says
"the built-in function does not evaluate the expression that was not chosen"
2) member pointers seemed interesting, eg. offsetof can be defined like this:
template< class C, class T >
int f( T C::*q ) {
return (int)&((*(C*)0).*q);
}
But I still didn't find a way to turn this into constexpr.
3) For now, here's another version:
#include <stdio.h>
#pragma pack(1)
template <class A, int x>
struct B {
int z;
void f( void ) {
printf( "x=%i\n", x );
}
};
#define STRUCT( A ) template< int N=0 > struct A {
#define CHILD( A, N, B, y ) }; template<> struct A<N> : A<N-1> \
{ B<A<N>,sizeof(A<N-1>)> y;
#define STREND };
STRUCT( A )
int x0;
int x1;
CHILD( A,1, B, y );
short x2;
CHILD( A,2, B, z );
char x3;
STREND
typedef A<2> A1;
int main( void ) {
A1 a;
a.y.f();
a.z.f();
}

For now, here's one MS-specific solution, still thinking how to make it more general
#include <stdio.h>
#define offs(s,m) (size_t)&(((s *)0)->m)
#define Child(A,B,y) \
__if_exists(X::y) { enum{ d_##y=offs(X,y) }; } \
__if_not_exists(X::y) { enum{ d_##y=0 }; } \
B<A,d_##y> y;
template <class A, int x>
struct B {
int z;
void f( void ) {
printf( "x=%i\n", x );
}
};
template< class X >
struct A {
int x0;
int x1;
Child(A,B,y);
Child(A,B,z);
};
typedef A<int> A0;
typedef A<A0> A1;
int main( void ) {
A1 a;
a.y.f();
a.z.f();
}

Assuming the calls actually need a reference to the containing object, just store the reference to the owner. Unless you have specific memory profiling evidence that it's causing a significant memory increase to store the extra references, just do it the obvious way.

Related

From enum type declared in a class/struct get to a peer static method also declared in that class/struct?

Briefly: In a template that takes an enum type as parameter (not a scoped enum, a regular old pre-C++11 enum) I need to call a method, declared in the same struct as the enum, which takes an enum value as its parameter. Is there a way to do this?
In full: Suppose I'm "self-scoping" unscoped enums as follows:
struct W {
enum E { A, B, C };
static string foo(enum E e);
};
Now suppose I have a bunch of these struct declarations following this pattern - each has an enum though the enum type's name is different and each has a static method foo taking one argument which is of that enum type.
Now I want to create a template that given a bunch of one of these enum types wants to transform each one according to its own foo():
template <typename E>
vector<string> xform(const vector<E> es) {
vector<string> ss;
for (E e : es) {
ss.push_back(foo(e));
}
return ss;
}
Now I instantiate xform:
...
vector<enum W::A> as{W::A, W::C};
auto Wx = xform(as);
...
and of course I get a compiler error because the compiler can't find the right foo to call:
prog.cc: In instantiation of 'std::vector<std::__cxx11::basic_string<char> > xform(std::vector<E>) [with E = W::A]':
prog.cc:34:24: required from here
prog.cc:24:21: error: 'foo' was not declared in this scope
24 | ss.push_back(foo(e));
| ~~~^~~
(This is all here on wandbox.)
So I need to get from the enum type to its peer method. Can I do that - how? (Since the peer method's name is always the same that part's easy - I don't know how to get from the enum type to its enclosing type.)
(Obviously I can solve this if the enum type's name in each struct is the same, by using the struct's name as the template argument. But in my use case the enums all have different names.)
Resolution (at this point): D-RAJ's answer though very simple doesn't work in this particular case because of the function foo is not dependent on the type parameter in the template function xform, thus the rules related to lookup and ADL and a non-dependent name in a template mean that ADL can not be used if you try to implicitly instantiate xform in code in some other namespace. (I'm not sure I understand why, but that's the fact.) The error is that the name cannot be found at the point of template instantiation, only at the point of declaration (and only then via ADL). I guess you could get around that with explicit instantiations ... but ...
dxiv's answer of using traits works great, is not onorous, and it can be done without modifying the existing wrapped-enums at all.
In simple, No, you cant do it like that. There are 2 reasons for this,
vector<enum W::A> and template <typename E> vector<string> xform(const vector<E> es) doesn't let you find which struct contains the function foo(). This is because the std::vector::_Ty = enum W::A which is basically an enum type. How can you find a struct from an enum type?
When you define the static foo() function in a struct or class, the function is in the scope of the struct/ class (its the same as namespace W { string foo(...) { ... } }). This is the reason for this error: prog.cc:24:21: error: 'foo' was not declared in this scope.
How to resolve this issue?
The only reasonable option that comes to my mind is to put the foo() function in the global scope and provide overrides to it. It would look something like this.
struct W1 {
enum A { A, B, C };
};
string foo(enum W1::A a) { return std::array{ "A","B","C" } [a] ; }
struct W2 {
enum B { X, Y, Z, };
};
string foo(enum W2::B b) { return std::array{ "X", "Y", "Z" } [b] ; }
Now the xform() function can resolve which foo() to be used at compile time without any scope issues.
I don't know that it's possible as stated, and don't think it is.
A relatively cheap alternative could be to maintain the association between names by hand. In the sample code below, this is done by specializations of a helper template WX<> (tried here).
#include <string>
#include <vector>
using std::string;
using std::vector;
struct W1 {
enum E1 { A, B, C };
static string foo(enum E1 e);
};
struct W2 {
enum E2 { A, B, C };
static string foo(enum E2 e);
};
template<typename T> struct WX;
template<> struct WX<W1::E1> { using W = W1; };
template<> struct WX<W2::E2> { using W = W2; };
template<typename E> vector<string> xform(const vector<E> es) {
vector<string> ss;
for (E e : es) {
ss.push_back(WX<E>::W::foo(e));
}
return ss;
}
void bar()
{
vector<enum W1::E1> a1s { W1::A, W1::C };
auto w1x = xform(a1s);
vector<enum W2::E2> a2s { W2::A, W2::C };
auto w2x = xform(a2s);
}

C++ 11 Template Variable Design [closed]

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";
}
}

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);

Reference-counting instances of classes based on their types

Consider the following code:
struct I
{
SomeInternalState m_internalState;
};
struct S
{
I * m_i;
set_I (I * i)
{
m_i = i;
makeSomeChangesToTheInternalStateOfI(m_i);
}
};
struct S_1 : S { ... };
struct S_2 : S { ... };
...
struct S_n : S { ... };
It is given that an arbitrary count of instances of S_1, ... S_n may be created, and all of them will call set_I() only once.
Now, I want the instances of S_1, ... S_n to makeSomeChangesToTheInternalStateOfI() only once per instance of I per type of S_x, so that I could call set_I() from different instances of the same class S_x with the same instance of I and be sure that the internal state of I will be modified only during the first call.
The likely decision is to put some dispatch table into I, but I can't think of a sensible key for it, based solely on the type of S_x instance and not involving any hand-written "runtime type id" constants for all possible types S_1, ... S_n.
How do I do it?
EDIT:
The points that I should have stressed:
1) There may be more than one instance of I at a time, and the S_x-classes should be able to change the state of multiple instances of I, but only once per each instance. That is:
I i1, i2;
S_1 s1a, s1b;
S_2 s2a, s2b;
// all possible combinations:
s1a.changeStateOfI(i1);
s1b.changeStateOfI(i1);
s2a.changeStateOfI(i1);
s2b.changeStateOfI(i1);
s1a.changeStateOfI(i2);
s1b.changeStateOfI(i2);
s2a.changeStateOfI(i2);
s2b.changeStateOfI(i2);
In this fragment, the states of both i1 and i2 should only be changed once by S_1's method (via s1a) and once by S_2's (via s2a).
2) I suppose, reference-counting could be used to solve the problem - there's no need to know exactly, how many times the initialisation occurred, it's enough to know if it did or not.
EDIT2
I've marked n.m.'s suggestion as the answer, though my final solution differs a bit. Here it is, so that others may use it too:
struct AbstractS
{
I * m_i;
virtual void set_I (I * i) = 0;
};
template <typename self_T>
struct RegS : AbstractS
{
static std::set<I *> s_registeredContexts;
virtual void set_I (I * i)
{
m_i = i;
if (i == NULL || s_registeredContexts.count(i) > 0) return;
makeSomeChangesToTheInternalStateOfI(i);
contexts.insert(i);
}
};
template <typename self_T>
std::set<I *> InterpreterState<self_T>::s_registeredContexts;
struct S_1 : RegS<S_1> { ... };
struct S_2 : RegS<S_2> { ... };
...
struct S_n : RegS<S_n> { ... };
The difference compared to n.m.'s variant is that I've used the CRTP pattern here instead of enumerating the instantiations, the thing I wanted to avoid too.
You can use typeinfo as a key, but it's a bad idea. You should not count types in your program. Let me explain with a simple example.
Let's say you have a Vehicle type and its descendants Car, Truck and Bike. You call your function once per each of these classes. So far so good. Now you need, for a completely unrelated reason, to handle SUVs, RacingCars, GarbageTrucks, Trikes, RedCars, ReddishCars and YellowishReddishWithGreenishTintCars. Your decision on the number of times your function is going to be called should be completely orthogonal to your decision about introducing or not introducing separate classes for each of these cases.
So you need something to tag your Vehicles as distinct or similar, solely for the purpose of calling your function once per a bunch of similar objects. One way to achieve that is with a class template and a bunch of type parameters (any kind of type parameters).
class ChangerOfInternalStateOfI
{
public:
ChangerOfInternalStateOfI (I* i) {
makeSomeChangesToTheInternalStateOfI(i);
}
};
template <int n>
class S_N : public S
{
public:
S_N() {
static ChangerOfInternalStateOfI changer;
}
};
typedef S_N<1> S_1;
typedef S_N<2> S_2;
You can use enum instead of int, or a typename, doesn't really matter. The point is that all of your ChangerOfInternalStateOfI are distinct because they belong to distinct classes, and each of the constructors is going to be called once.
If the way with static data member n.m. mentioned doesn't meet the objective,
how about having a set containing types processed before in I?
As type_info itself isn't less-than-comparable, a simple wrapper
type_info_ is used in the following code.
If type-check has to be done polymorphically(through base class S),
runtime type information is needed.
So I made changeStateOfI be virtual.
#include <typeinfo>
#include <set>
using namespace std;
struct type_info_ {
type_info const *t;
type_info_( type_info const* t ) : t( t ) {}
bool operator<( type_info_ const& x ) const { return t->before( *x.t ); }
};
struct I {
set< type_info_ > types;
void f( type_info const& t, char const* s ) {
if ( types.insert( type_info_( &t ) ).second ) { puts( s ); }
}
};
struct S {
virtual void changeStateOfI( I& i, char const* s ) {
i.f( typeid( *this ), s );
}
};
struct S_1 : S {};
struct S_2 : S {};
int main() {
I i1, i2;
S_1 s1a, s1b;
S_2 s2a, s2b;
s1a.changeStateOfI(i1, "s1a i1");
s1b.changeStateOfI(i1, "s1b i1");
s2a.changeStateOfI(i1, "s2a i1");
s2b.changeStateOfI(i1, "s2b i1");
s1a.changeStateOfI(i2, "s1a i2");
s1b.changeStateOfI(i2, "s1b i2");
s2a.changeStateOfI(i2, "s2a i2");
s2b.changeStateOfI(i2, "s2b i2");
}
The above code printed s1a i1, s2a i1, s1a i2, s2a i2
in my environment.

Can templates be used to access struct variables by name?

Let's suppose I have a struct like this:
struct my_struct
{
int a;
int b;
}
I have a function which should set a new value for either "a" or "b". This function also requires to specify which variable to set. A typical example would be like this:
void f(int which, my_struct* s, int new_value)
{
if(which == 0)
s->a = new_value;
else
s->b = new_value;
}
For reasons I won't write here I cannot pass the pointer to a/b to f. So I cannot call f with address of my_struct::a or my_struct::b.
Another thing I cannot do is to declare a vector (int vars[2]) within my_struct and pass an integer as index to f. Basically in f I need to access the variables by name.
Problem with previous example is that in the future I plan to add more variables to struct and in that case I shall remember to add more if statements to f, which is bad for portability.
A thing I could do is write f as a macro, like this:
#define FUNC(which)
void f(my_struct* s, int new_value) \
{ \
s->which = new_value; \
}
and then I could call FUNC(a) or FUNC(b).
This would work but I don't like using macros.
So my question is: Is there a way to achieve the same goal using templates instead of macros?
EDIT: I'll try to explain why I cannot use pointers and I need access to variable by name.
Basically the structure contains the state of a system. This systems needs to "undo" its state when requested. Undo is handled using an interface called undo_token like this:
class undo_token
{
public:
void undo(my_struct* s) = 0;
};
So I cannot pass pointers to the undo method because of polymorphism (mystruct contains variables of other types as well).
When I add a new variable to the structure I generally also add a new class, like this:
class undo_a : public undo_token
{
int new_value;
public:
undo_a(int new_value) { this->new_value = new_value; }
void undo(my_struct *s) { s->a = new_value}
};
Problem is I don't know pointer to s when I create the token, so I cannot save a pointer to s::a in the constructor (which would have solved the problem).
The class for "b" is the same, just I have to write "s->b" instead of s->a
Maybe this is a design problem: I need an undo token per variable type, not one per variable...
To answer the exact question, there is, but it's pretty complicated, and it will purely be a compile-time thing. (If you need runtime lookup, use a pointer-to-member - and based on your updated question, you may have misunderstood how they work.)
First, you need something you can use to represent the "name of a member" at compile time. In compile-time metaprogramming, everything apart from integers has to be represented by types. So you'll use a type to represent a member.
For example, a member of type integer that stores a person's age, and another for storing their last name:
struct age { typedef int value_type; };
struct last_name { typedef std::string value_type; };
Then you need something like a map that does lookup at compile time. Let's called it ctmap. Let's give it support for up to 8 members. Firstly we need a placeholder to represent the absence of a field:
struct none { struct value_type {}; };
Then we can forward-declare the shape of ctmap:
template <
class T0 = none, class T1 = none,
class T2 = none, class T3 = none,
class T4 = none, class T5 = none,
class T6 = none, class T7 = none
>
struct ctmap;
We then specialise this for the case where there are no fields:
template <>
struct ctmap<
none, none, none, none,
none, none, none, none
>
{
void operator[](const int &) {};
};
The reason for this will be come clear (possibly) in a moment. Finally, the definition for all other cases:
template <
class T0, class T1, class T2, class T3,
class T4, class T5, class T6, class T7
>
struct ctmap : public ctmap<T1, T2, T3, T4, T5, T6, T7, none>
{
typedef ctmap<T1, T2, T3, T4, T5, T6, T7, none> base_type;
using base_type::operator[];
typename T0::value_type storage;
typename T0::value_type &operator[](const T0 &c)
{ return storage; }
};
What the hell's going on here? If you put:
ctmap<last_name, age> person;
C++ will build a type for person by recursively expanding the templates, because ctmap inherits from itself, and we provide storage for the first field and then discard it when we inherit. This all comes to a sudden stop when there are no more fields, because the specialization for all-none kicks in.
So we can say:
person[last_name()] = "Smith";
person[age()] = 104;
It's like looking up in a map, but at compile time, using a field-naming class as the key.
This means we can also do this:
template <class TMember>
void print_member(ctmap<last_name, age> &person)
{
std::cout << person[TMember()] << std::endl;
}
That's a function that prints one member's value, where the member to be printed is a type parameter. So we can call it like this:
print_member<age>(person);
So yes, you can write a thing that is a little like a struct, a little like a compile-time map.
#include <iostream>
#include <ostream>
#include <string>
struct my_struct
{
int a;
std::string b;
};
template <typename TObject, typename TMember, typename TValue>
void set( TObject* object, TMember member, TValue value )
{
( *object ).*member = value;
}
class undo_token {};
template <class TValue>
class undo_member : public undo_token
{
TValue new_value_;
typedef TValue my_struct::* TMember;
TMember member_;
public:
undo_member(TMember member, TValue new_value):
new_value_( new_value ),
member_( member )
{}
void undo(my_struct *s)
{
set( s, member_, new_value_ );
}
};
int main()
{
my_struct s;
set( &s, &my_struct::a, 2 );
set( &s, &my_struct::b, "hello" );
std::cout << "s.a = " << s.a << std::endl;
std::cout << "s.b = " << s.b << std::endl;
undo_member<int> um1( &my_struct::a, 4 );
um1.undo( &s );
std::cout << "s.a = " << s.a << std::endl;
undo_member<std::string> um2( &my_struct::b, "goodbye" );
um2.undo( &s );
std::cout << "s.b = " << s.b << std::endl;
return 0;
}
In addition to Daniel Earwicker's answer, we can use variadic templates in the new C++ standard to achieve the same.
template <typename T>
struct Field {
typename T::value_type storage;
typename T::value_type &operator[](const T &c) {
return storage;
}
};
template<typename... Fields>
struct ctmap : public Field<Fields>... {
};
This code is cleaner and does not have fixed bound of members. You can use it in the same way
struct age { typedef int value_type; };
struct last_name { typedef std::string value_type; };
ctmap<last_name, age> person;
person[last_name()] = "Smith";
person[age()] = 104;
Mykola Golubyev's answer is good, but it can be improved slightly by using the fact that pointers to members can be used as non-type template parameters:
#include <iostream>
#include <ostream>
#include <string>
struct my_struct
{
int a;
std::string b;
};
template <typename TObject, typename TMember, typename TValue>
void set( TObject* object, TMember member, TValue value )
{
( *object ).*member = value;
}
class undo_token {};
template <class TValue, TValue my_struct::* Member>
class undo_member : public undo_token
{
// No longer need to store the pointer-to-member
TValue new_value_;
public:
undo_member(TValue new_value):
new_value_(new_value)
{}
void undo(my_struct *s)
{
set( s, Member, new_value_ );
}
};
int main()
{
my_struct s;
set( &s, &my_struct::a, 2 );
set( &s, &my_struct::b, "hello" );
std::cout << "s.a = " << s.a << std::endl;
std::cout << "s.b = " << s.b << std::endl;
undo_member<int, &my_struct::a> um1( 4 );
um1.undo( &s );
std::cout << "s.a = " << s.a << std::endl;
undo_member<std::string, &my_struct::b> um2( "goodbye" );
um2.undo( &s );
std::cout << "s.b = " << s.b << std::endl;
return 0;
}
This shaves off the cost of a pointer to member from each instance of undo_member.
I'm not sure why you cannot use a pointer so I don't know if this is appropriate, but have a look at C++: Pointer to class data member, which describes a way you can pass a pointer to a data member of a struct/class that does not point directly to the member, but is later bound to a struct/class pointer. (emphasis added after the poster's edit explaining why a pointer cannot be used)
This way you do not pass a pointer to the member - instead it is more like an offset within a object.
It sounds like what you're looking for is called "reflection", and yes it's often implemented with some combination of templates and macros. Be warned that reflection solutions are often messy and annoying to work with, so you may want to do some research into them before you dive into the code to find out if this is really what you want.
Second hit on Google for "C++ reflection templates" was a paper on "Reflection support by means of template metaprogramming". That should get you started. Even if it's not quite what you're looking for, it may show you a way to solve your problem.
You can't use templates to solve this, but why use a struct in te first place? This seems like an ideal use for a std::map which would map names to values.
From what you described, i am guessing you have no way of redefining the structure.
If you did, i'd suggest you use Boost.Fusion to describe your structure with template-named fields. See associative tuples for more information on that. Both kinds of structures might actually be compatible (same organization in memory), but i'm pretty sure there is no way to get such a guarantee from the standard.
If you don't, you can create a complement to the structure that would give you access to fields the same way that associative tuples do. But that can be a bit verbal.
EDIT
Now it's pretty clear that you can define the structures the way you want to. So i definitely suggest you use boost.fusion.
I can't think of a reason why you would not have everything at hand when creating an undo command. What you want to be able to undo, you have done. So i believe you can use pointers to class members and even pointers to the fields of a particular class instance when creating the undo command.
You're right in your EDIT section. It is a matter of design.