0

This is a little hard to describe in words, I'll start with a snippet and try to explain what is attempted as best I can.

struct NonTrivialBase {
    virtual void TakeAction();
    virtual ~NonTrivialBase();
};

template< typename P >
struct NonTrivial_D1 : NonTrivialBase
{
    P case1;

    virtual void TakeAction() {
        // do something with case1
    }

    NonTrivial_D1( P arg ) : case1(arg) {
    }
};

template< typename Q >
struct NonTrivial_D2 : NonTrivialBase
{
    Q case2;

    virtual void TakeAction() {
        // do something with case2
    }

    NonTrivial_D2( Q arg, int arg2 ) : case2(arg,arg2) {
    }
};

class Unit
{
    NonTrivialBase * Member;

  public:

    template< typename P2 >
    Unit (P2 par) : Member ( new NonTrivial_D1<P2>(par) ) {}

    template< typename Q2 >
    Unit (Q2 par, int par2) : Member ( new NonTrivial_D2<Q2>(par,par2) ) {}
};

template< unsigned short Count >
class Collection
{
    Unit units[ Count ];

  public:

    template< typename P3 >
    Collection( P3 par )
    //  : units { [ 0 ... Count - 1 ] = {par} }
    // ^^ problem
    {}

    template< typename Q3 >
    Collection( Q3 par, int arg )
    //  : units { [ 0 ... Count - 1 ] = {par, arg} }
    // ^^ problem
    {}

};

If it isn't clear (may not be) I'm trying to come up with a container class that can initialize an array of non-trivially-constructed objects, all of which will have the same parameters to whichever constructor is deemed valid. The essence of the design is Collection and Unit have the same constructors in order to manage a compile-time-known number of identically-constructed "units" only through Collection references.

For various reasons it is not possible to initialize Unit without a constructor. Both Collection and Unit classes are intended to act as base classes themselves.

I expect something like this to work but again, std::array is not available in my environment (GCC 4.8.1-4 / MinGW) and I want to avoid if possible including other libraries just for this one thing. Boost isn't an option for me, for example.

Then, the array-initializer syntax itself.

I understand this is GCC-only but that isn't a problem. I can't even get the syntax to behave correctly when the array-element type requires template parameters for the constructor (automatically determined or not, I can live with either). I get an error to the equivalent of:

error: expected identifier before numeric constant
: units { [ 0 ... Count - 1 ] = {par} }
            ^

I believe that the array-range initializer in and of itself should be supported, courtesy of this reference.

And lastly I just need to be clear that this solution is not scalable because of Count

Unit units[Count] = { {param}, {param}, ... }

such as suggested here.

In the grand scheme of things I don't have to do it this way but now that I have had the idea, I'm genuinely curious how to approach this...

Relevant GCC parameters (just in case) - g++ -std=gnu++0x -O3 -Wall -Wconversion -c -fmessage-length=0

EDIT

To clarify some requirements -

Heap vs Stack - preference is for stack but I can live with heap-based solutions. Bear in mind Unit may not be copyable.

std::array - I cannot use this. The suggested duplicate relies on this being available.

Community
  • 1
  • 1
Xeren Narcy
  • 875
  • 5
  • 15
  • 3
    Using `std::vector` would be the simplest solution – milleniumbug Jun 16 '16 at 14:38
  • @milleniumbug and not the same thing. a "stack"-allocated array is not the same as a "heap"-allocated array! – rubenvb Jun 16 '16 at 14:42
  • @rubenvb Which is not really relevant here. At least not until OP adds a hard requirement for it. – milleniumbug Jun 16 '16 at 14:48
  • @Xeren also, GCC 4.8.1 does have a functional ``, it seems you stumbled upon a broken build, see [this question](http://stackoverflow.com/questions/25234986/suspected-stdarray-c11-library-is-broken-what-do-i-do). I highly recommend either fixing the typo in the `array` header file or just getting a non-broken toolchain. Also, get a MinGW-w64 version from here: http://mingw-w64.sourceforge.net. – rubenvb Jun 16 '16 at 14:57
  • @milleniumbug to confirm (it's late and I'm losing my mind on this) using `std::vector` would be heap-based? In that case I'd just loop-construct in `Collection`'s constructors via emplace? – Xeren Narcy Jun 16 '16 at 14:57
  • @rubenvb checked just now, it's not a typo, it is indeed `struct array`. However inspecting the header the whole thing is hidden in preprocessing due to `__cplusplus < 201103L` cutting off the definition in favor of a c++0x_warning.h file (it is 199711L for reasons I dont know) – Xeren Narcy Jun 16 '16 at 15:02
  • @XerenNarcy Try compiling with `-std=c++11` instead of `-std=gnu0x`. Also, the linked solution works for anything that is initializable from an initializer list. Although that then precludes initializing non-copyable objects (init lists take a copy of the value). – rubenvb Jun 16 '16 at 15:05
  • 1
    @XerenNarcy Yup, it's heap-based. With `std::vector` you could call `vec.reserve(Count);` and then call `Unit unit = { par }; vec.push_back(unit);` in a loop. – milleniumbug Jun 16 '16 at 15:09
  • @rubenvb mkay... tried it, no luck in fact breaks things further such as this for whatever reason - `c:\mingw\include\math.h: In function 'float hypotf(float, float)': c:\mingw\include\math.h:635:30: error: '_hypot' was not declared in this scope { return (float)(_hypot (x, y)); }` . I had it to gnu for a reason lol... – Xeren Narcy Jun 16 '16 at 15:10
  • @milleniumbug Thanks, I think without going insane making this work on my environment, that's probably going to be as elegant as possible under the circumstances. – Xeren Narcy Jun 16 '16 at 15:11

0 Answers0