Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Possible to pass name as argument to c++ template?

Tags:

c++

templates

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.

like image 958
anon Avatar asked Feb 19 '10 00:02

anon


People also ask

Which of the following can be passed as type arguments to templates?

Explanation: A template parameter is a special kind of parameter that can be used to pass a type as argument. 2.

Can there be more than one arguments to templates?

Can there be more than one argument to templates? Yes, like normal parameters, we can pass more than one data type as arguments to templates.

Can we use template in C?

The main type of templates that can be implemented in C are static templates. Static templates are created at compile time and do not perform runtime checks on sizes, because they shift that responsibility to the compiler.

CAN default arguments be used with the template class?

Default parameters for templates in C++: Like function default arguments, templates can also have default arguments.


2 Answers

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.

like image 159
Georg Fritzsche Avatar answered Nov 07 '22 19:11

Georg Fritzsche


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.

like image 23
Omnifarious Avatar answered Nov 07 '22 18:11

Omnifarious