0

I have memory allocator which allocates memory for an object and calls its constructor with any given arguments, see below.

 // 0 args to constructor template <class T> inline T* AllocateObject() { return new (InternalAllocate(sizeof(T), alignof(T))) T(); } // 1 args to constructor template <class T, typename arg0> inline T* AllocateObject(const arg0& a0) { return new (InternalAllocate(sizeof(T), alignof(T))) T(a0); } template <class T, typename arg0> inline T* AllocateObject(arg0& a0) { return new (InternalAllocate(sizeof(T), alignof(T))) T(a0); } // 2 args to constructor template <class T, typename arg0, typename arg1> inline T* AllocateObject(arg0& a0, arg1& a1) { return new (InternalAllocate(sizeof(T), alignof(T))) T(a0,a1); } template <class T, typename arg0, typename arg1> inline T* AllocateObject(const arg0& a0, arg1& a1) { return new (InternalAllocate(sizeof(T), alignof(T))) T(a0,a1); } template <class T, typename arg0, typename arg1> inline T* AllocateObject(arg0& a0, const arg1& a1) { return new (InternalAllocate(sizeof(T), alignof(T))) T(a0,a1); } template <class T, typename arg0, typename arg1> inline T* AllocateObject(const arg0& a0, const arg1& a1) { return new (InternalAllocate(sizeof(T), alignof(T))) T(a0,a1); } //......... 

As you can see the number of calls grows with quite rapidly with the number of arguments. I have to alternate with 'const' and 'non-const' for each argument to make sure it plays fine with any argument I pass. (specifically, to be able to pass by references aswell as pass by value)

Is there any better way to perform the same task than to repeat this scheme? Basically I am looking at something like 8-10 arguments max and its just not very feasible I feel.

Thanks

5
  • 2
    If you never change the arguments, just use const type & to handle all 4 versions at once. Commented Aug 30, 2012 at 17:53
  • 2
    Is C++11 an option for you? It contains updates to the language very specific for this exact problem. EDIT: Well you're using alignof so shame on me for not reading more carefully. :) FireRain's answer is what I was alluding to. Commented Aug 30, 2012 at 17:53
  • C++11 is Not an option unfortunately Commented Aug 30, 2012 at 18:31
  • can you show an example chris? Commented Aug 30, 2012 at 18:32
  • also - how would that work if the c onstructor of the object might change the argument? Commented Aug 30, 2012 at 19:07

2 Answers 2

4

You can use a variadic template.

template <class T, class... Args> inline T* AllocateObject(Args&&... args) { return new (InternalAllocate(sizeof(T), alignof(T))) T(std::forward<Args>(args)...); } 

The std::forward call will preserve any references and constness.


Note that this requires C++11. Most recent compilers already support variadic templates (I am unsure about Microsoft’s, though).

Sign up to request clarification or add additional context in comments.

10 Comments

And if you need to enforce a maximum number of arguments, static_cast combined with sizeof args... will do the trick nicely.
Too bad there really isn't any compiler that really supports it yet. (a very new version of gcc does a bit I think)
@BobFincheimer, I've been using variadic templates on GCC for a while now. Wasn't it way back at 4.6.1?
@BobFincheimer clang and gcc supports if fully
@BobFincheimer GCC and clang support variadic templates. I am only unsure about MSVC, which did have trouble with it. That may be fixed by now, but I don’t use Windows.
|
1

Not a template solution, but a variable arguments #define could help you out of this problem.
The exact format depends on your compiler, but in MSVC it would look like this:

#define ALLOCATE_OBJECT(TYPE, ...) \ ( new( InternalAllocate(sizeof(TYPE), alignof(TYPE)) ) TYPE(__VA_ARGS__) ) 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.