0

I want to initialize my array items while avoiding unnecessary instances and copies (similar to this question: initialize std::array without copying/moving elements).

An initializer list does work for a small amount of objects.

Bit I want to do this via a code snippet since my array has several hundreds of items...

How can I do this?

#include <array>
#include <iostream>

class mytype {
public:
    int a;
    mytype() : a(0) {}
    mytype(int a) : a(a) {}
};

int main() {
    // explict constructor calls to instantiate objects does work
    std::array<mytype, 2> a = { { mytype(10), mytype(20) } };
    std::cout << a[0].a;  // 10

    // I want to do something like this - what does not work of course
    std::array<mytype, 2> b = { { for (i = 0, i++, i < 2) mtype(10 * i); } };
}
6
  • 1
    Related: stackoverflow.com/questions/37602057/… Commented Dec 2, 2018 at 12:59
  • 2
    coliru.stacked-crooked.com/a/d31aa7703ce20d9b Commented Dec 2, 2018 at 13:06
  • @πάνταῥεῖ THX + yes, looks related and does explain why a for loop is not a compile time expression. But how would a solution to constructor initialization looks like? Commented Dec 2, 2018 at 13:07
  • 1
    Use a recursive template may be. Commented Dec 2, 2018 at 13:10
  • @πάνταῥεῖ THX, I understand (damn clever but complicated solution for a simple problem ;-) Commented Dec 2, 2018 at 13:15

2 Answers 2

1

In :

#include <array>
#include <utility>
#include <cstddef>

template <typename T, std::size_t... Is>
std::array<T, sizeof...(Is)> to_array(std::index_sequence<Is...>)
{
    return { T(Is*10)... };
}

template <typename T, std::size_t N>
std::array<T, N> to_array()
{
    return to_array<T>(std::make_index_sequence<N>{});
}

int main() 
{
    std::array<mytype, 10> b(to_array<mytype, 10>());
}

DEMO

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

Comments

1

This is typically accomplished with a pair of templates:

namespace detail {
    template<std::size_t... Idx>
    auto make_mytype_array(std::index_sequence<Idx...>) {
        return std::array<mytype, sizeof...(Idx)>{{
            mytype(10 * Idx)...
        }};
    }
}

template<std::size_t N>
auto make_mytype_array() {
    return detail::make_mytype_array(make_index_sequence<N>{});
}

The above are a pair of utility free functions, but can be folded into the class if need be. If you need it for more than just an expression like 10*i, then a lambda can be passed as another argument (templated to be a general "callable"). With copy elision this will all collapse into direct initialization of the result array object.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.