2

Is it possible to "pass" somehow a static initializer list at construction time to a container wrapper class that than in turn initializes its member?

struct bar {
  bar(void * ptr): ptr(ptr) {}
  void * ptr;
};

template<class T, int N>
struct foo
{
  foo( args ) :store(args)  {}  // here the arg list should be passed

  T store[N];
};

int main()
{
  bar b[2]={NULL,NULL};
  foo<bar,2> f(NULL,NULL); // This should be possible
}

Unfortunately I cannot use STL or Boost.

Let me just explain, if you doubt the usefulness of this. First, this is a very "cooked-down" setup. Explaining the whole setup is not adequate to post here nor would it help. Just imagine a case, where you have a nested expression template tree, you traverse it at compile-time and collect the involved objects and store them in a container wrapper like the above. If you have further question please ask.

Edited: The default constructor of T should not be called.

ritter
  • 7,447
  • 7
  • 51
  • 84
  • C++0x makes this easy. I'll have a go at a C++98 answer though – Flexo Aug 20 '11 at 11:35
  • Thanks! Sorry, I can't use c++0x. – ritter Aug 20 '11 at 11:56
  • http://stackoverflow.com/questions/161790/initialize-a-const-array-in-a-class-initializer-in-c They're talking about a const array there, but it's the same underlying problem – Flexo Aug 20 '11 at 12:35
  • I take it you can't/won't add a level of indirection by making `store` be an array of pointers? – Flexo Aug 20 '11 at 12:38
  • 1
    “Unfortunately I cannot use STL or Boost.” – why? This sounds moronic. It’s like using C# and being unable to use the `String` class. Or all of the .NET framework, in fact. – Konrad Rudolph Aug 20 '11 at 13:31
  • @Konrad - possibly some embedded device? That was my assumption anyway. – Flexo Aug 20 '11 at 14:09
  • This code piece gets compiled by NIVIDA CUDA Frontend++. There is some support for STL (via thrust) -- but not in kernel code. Thrust tries to make your life easier if you write host code. I am working on a JIT compilation solution for expression templates. – ritter Aug 20 '11 at 15:36
  • @Frank That’s a valid reason. Thanks. – Konrad Rudolph Aug 20 '11 at 15:55

1 Answers1

2

Method 1: va_args

If you agree to make bar POD this can be done with va_args:

#include <stdarg.h>

struct bar {
  void * ptr;
};

template<class T, int N>
struct foo
{
  foo(...)  { // here the arg list should be passed
    va_list ap;
    va_start(ap, N);

    for (int i = 0; i < N; ++i) {
      store[i] = va_arg(ap, T);
    }
    va_end(ap);
  }

  T store[N];
};

int main()
{
  foo<bar,2> f(bar(),bar());
}

It's not great though - you have to trust the caller a little too much for my liking and the POD requirement could be quite limiting.

Method 2: range

If you agree to make your type T both default constructable and assignable you can use this method:

#include <assert.h>
#include <stdlib.h>

struct bar {
  bar(void * ptr): ptr(ptr) {}
  bar() {}
  void * ptr;
};

template<class T, int N>
struct foo
{
  foo(T *begin, const T *end)  { // here the arg list should be passed
    // Normally I'd use std::copy here!
    int i = 0;
    while (begin != end) {
       assert(i < N);
       store[i] = *begin++;
    }
  }

  T store[N];
};

int main()
{
  bar b[2]={NULL,NULL};
  foo<bar,2> f(&b[0], &b[sizeof(b)/sizeof(bar)]);
}

It's not quite seamless - you end up with both an array and an instance of your object, but you can make the array static const and kept well hidden from the rest of the code at least.

Method 3: operator overloading tricks

You could also use a trick with operator, to reduce all of the items into one parameter, which IIRC is similar to what Boost.Assign does.

Flexo
  • 87,323
  • 22
  • 191
  • 272
  • Thanks Awoodland! Nice solutions. Unfortunately both have the same problem: The standard constructor of T is called at construction time of the wrapper class. Instead a constructor taking arguments should be called, like in my original code for the first definition of "b". – ritter Aug 20 '11 at 12:00
  • I don't think it's possible without either new syntax (C++0x) or copy constructing them/assigning from elsewhere. – Flexo Aug 20 '11 at 12:20