C++ template metaprogramming question

Started by
8 comments, last by CoffeeMug 14 years, 4 months ago
Suppose I have the following piece of code:

class foo_t
{
public:
    template<typename T> void bar()
    {
        // ...
    }
};



What I would like to do is to have every instance of the bar function to have its own member variable within foo_t (or something similar, like an indexed array). It seems that at compile time I can know how many different bar() functions were instantiated, so I should be able to have a member array in foo_t, and for every bar() function I could index into that array. Unforunately I don't know how to accomplish this - I'm new to C++ template trickery. An easy way I can think of is to place a static variable within bar, but I need this to be stored per runtime instance of foo_t. Is there a good way to do this?
Advertisement
You can't really add member variables for each template instantiation because the compiler would like to know the exact size of the class after parsing the header. I can't see any way to make this work easily.

It should be possible to have an std::map<std::string, boost::any> or some such data member though and using typid(T).name() as a key.
I've already done this with a hash table, but unfortunately a runtime lookup decreases performance by a factor of three, and this is a performance critical piece. I could force people to code these things manually, but it would be really really nice to find an automatic solution.
What about not adding a templated function but instead a set number of instances of some templated helper class? If it defines the right operator () it will behave just like a function and would be able to store the required member data as its own variable.

Edit: Of course they can't share a name and be only identified by the type like foo<T>, so that's a bit useless as well...

[Edited by - BitMaster on November 27, 2009 7:08:57 AM]
What about a static variable in the templated function which is a std::map<foo_t*, T>? Still a dynamic lookup but maybe faster without RTTI and string comparisons? On the other hand, it's even more of a horrible hack and offers a lot of open questions.

I prefer to avoid macros whenever possible, but this might be the only solution if you really want to get it done in one line.
Have the foo<T> function do something like assert(false) and a macro adds a sensible specialization together with the required data member to the class.
When people encounter a problem, they think of regular expressions as a solution. Now they have two problems.


Templates are similar.


What is the actual problem you are trying to solve?

Quote:so I should be able to have a member array in foo_t, and for every bar() function I could index into that array


Which also means that if enough different types are used, cache misses will become a hidden problem. Nothing will change, calls will just start taking longer.
Well, in my current implementation I don't use any RTTI or string comparisons (it's all hashed integers), and that's what gives me poor performance.

Could you give an example of what you mean by using macros? I'm not quite sure what you're referring to (I thought of using macros, but couldn't figure out a good way).
I thought about something like this:

#define MY_FUNCTION_MAKER(type, varName) private:    type varName; public:    template <> bar<type>()class foo_t{public:   template <typename T> bar()   {      assert(false);   }   MY_FUNCTION_MAKER(std::string, my_string)   {       // type specific code   }   MY_FUNCTION_MAKER(int, my_int)   {       // type specific code   }};


Not guaranteed to compile, probably needs a bit of work, especially regarding the exact way the compiler would like to know about template specializations. It's been a longish day already.
Quote:Original post by Antheus
When people encounter a problem, they think of regular expressions as a solution. Now they have two problems.


Templates are similar.


What is the actual problem you are trying to solve?
I agree. It feels like you're trying to get the right solution to the wrong problem here.
Once more for emphasis [smile]: What is the actual problem you are trying to solve?
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms
I'm a bit of a lisper at heart, so I was hoping to use C++ templates to feed my lisp macro frenzy - I wanted the compiler to generate some code for me. I ended up doing something similar, but not exactly what I described here - I still get compile time resolution, but the syntax for using it is a bit ugly. It's not worth going over the solution.

I was implementing a small object allocator system, and I wanted a class that would create a pool for each small object type I need (instead of creating the pools manually). So saying something like allocator.malloc<foo_t>() would add the code for a pool of foo_t objects. I didn't want to do it at runtime for performance reasons.

Thanks to everyone for your help!

This topic is closed to new replies.

Advertisement