tags:

views:

118

answers:

2

Is it possible to write a class:

template<typename T, ... name> struct Magic {
  T name;
};

such that:

Magic<int, foo> gives:

Magic<int, foo> {
  int foo;
}

and

Magic<float, bar> gives:

Magic<float, bar> {
  float bar;
}

Basically, I want to be able to specify not only the Type, but also the name of the member variables.

+5  A: 

That is not possible, you have to resort to either macro-based solutions or use a predefined set of types that provide named members.

A possible macro-based approach:

#define MAGIC(name_) \
    template<typename T> struct Magic1 { \
        T name_; \
    };

MAGIC(foo);

or:

#define MAGIC(type_, name_) \
    struct Magic1 { \
        type_ name_; \
    };

MAGIC(foo);

Using preprocessor magic, e.g. utilizing Boost.Preprocessor, you should be able to generate n named members in a more convenient way.

Another approach might be using a predefined set of classes providing certain named members from that you inherit:

enum { MemberNameFoo, MemberNameBar };

template<class T, int id>
struct named_member;

template<class T>
struct named_member<T, MemberNameFoo> {
    T foo;
};

template<class T>
struct named_member<T, MemberNameBar> {
    T bar;
};

// holder for the above, just one member for this example:

template<class T, int name>
struct holder : named_member<T, name> {};

// using it:

typedef holder<int, MemberNameFoo> HasFoo;
typedef holder<int, MemberNameBar> HasBar;

Using compile-time lists you could then inherit from n named_member instantiations, Boost.MPL could help here.

Georg Fritzsche
If you don't actually care too much what your members are named exactly, you can do this with typelists or in C++0x variadic templates. I've done it to implement classes that wrote their own serialization and deserialization methods.
Omnifarious
But the question is about wether its *"possible to pass name[s]"* to a template, not how to generate a holder for some arbitrarily named collection of types.
Georg Fritzsche
@gf, this is true. Though often people don't ask the question they exactly mean. They have a solution in mind for a problem and ask how to make the solution work, not how to solve the actual problem. :-)
Omnifarious
Right, but unless i can guess what exact problem underlies the question it is all highly speculative until clarified.
Georg Fritzsche
+1  A: 

No, it's not possible. There is a construct called a typelist that can be used to sort of achieve an effect like you're after. Unfortunately, even then you won't get named members, you will get accessor functions with names like MyClass::getField<1>().

In C++0x you can do better than typelists with variadic templates. But you will still have accessor functions that look just like the C++ case.

It's tempting to put down a variadic template example here because it wouldn't be too huge. Unfortunately I think that doing it well would require a few hours of research on my part to learn exactly how variadic templates worked. I could do a stupid version relatively easily, but I expect the stupid version would be a lot less nice in various ways than a well done version.

Omnifarious