开发者

static initializer list for wrapper class

开发者 https://www.devze.com 2023-03-29 05:37 出处:网络
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?

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. Expl开发者_高级运维aining 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.


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号