5

I want to initialize a template sized array of objects with no default constructors, as shown in following code :

#include <array>

template<std::size_t N>
class Foo
{
    public:
        class Bar
        {
                Foo<N> & _super;

            public:
                Bar(Foo<N> *super) :
                    _super(*super)
                {
                }
        };

        std::array<Bar, N>  _array;

        Foo(void) :
            _array{{}} // We need {this, ...} N times
        {
        }
};


int main(void)
{
    Foo<3>  foo;
    (void)foo;
    return 0;
}

Is it a way to say : "I want an array of N objects, all initialized with this same parameter" ? I think there is a way with the template meta programming, but I cannot figure how to do it.

6
  • Shouldn't Bar's constructor be Bar(Foo<N> &super) : _super(super)? Or member Foo<N> & _super should be Foo<N> * _super? Commented Apr 25, 2016 at 13:53
  • @flatmouse Does not change anything, no ? I could write it and construct Bar as follow Bar(*this) ; but that does not help solving the question. Commented Apr 25, 2016 at 13:56
  • Ah ok, you are taking a pointer which is then deferenced to initialize the reference member. I was trying to understand. I get it now. Commented Apr 25, 2016 at 13:58
  • related: stackoverflow.com/questions/17923683/… Commented Apr 25, 2016 at 13:59
  • @NathanOliver I cannot see how it is a duplicate... Commented Apr 25, 2016 at 14:00

2 Answers 2

9

Everything is possible with the little help from make_index_sequence:

   Foo() : Foo(std::make_index_sequence<N>()) {} 
   template <size_t... I> Foo(std::index_sequence<I...> ) : _array{((void)I, this)...} {}

Notice the comma operator (,) in the _array constructor - courtesy of @Quentin (as opposed to function call).

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

8 Comments

You can replace the function invocation with a comma operator : _array{(I, this)...} :)
Sure ! I didn't want to post an answer that be identical to yours, save for this tweak.
That seems a really convenient way to do this, but that necessitates the C++14. Is it possible in C++11 ?
@Boiethios, you can easily implement make_index_sequence in C++11. Let me post the code.
@SergeyA Thanks. It's because the compiler we use is C++11.
|
2

You could just keep adding one this at a time until you have N of them, at which point you just initialize _array:

    Foo()
    : Foo(this)
    { }

private:
    template <class... T, std::enable_if_t<(sizeof...(T) < N), void*> = nullptr>
    Foo(T... args)
    : Foo(args..., this)
    { }

    template <class... T, std::enable_if_t<(sizeof...(T) == N), void*> = nullptr>
    Foo(T... args)
    : _array{{args...}}
    { }  

3 Comments

@Boiethios The index_sequence approach is better.
Is it possible to write this code in C++11 (enable_if_t is C++14) ? For example with a template parameter size_t I that will decrease and a specialized version <0> ? I try to do this, but I have trouble with the writing of templates.
@Boiethios enable_if_t is just an alias template, you could just copy the definition in C++11.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.