4

suppose we have the following class in C++11 or later:

class MyClass {
private:
    const std::array<SomeType, 100> myArray;
public:
    explicit MyClass(std::array<SomeOtherType, 100> initArray);
};

Assuming that class SomeType has a constructor that takes a single SomeOtherType as an argument, is it possible to initialize the const member array using list-initialization in the constructor? What is the syntax for doing so?

Clearly, just directly initializing it like this doesn't work:

MyClass::MyClass(std::array<SomeOtherType, 100> initArray) :
    myArray{initArray} {}

Thanks!

4
  • 2
    You are aware that your class with a const member won't be copyable? Commented Nov 27, 2018 at 3:55
  • if you are using c++11 (or newer), look up documentation for std::initializer_list. If you are compiling with GCC, you may also find this post useful stackoverflow.com/questions/8192185/… Commented Nov 27, 2018 at 3:58
  • @Swordfish: Thanks for the heads up - that shouldn't be a problem for my current use case, but I'll keep that in mind for the future. Commented Nov 27, 2018 at 4:37
  • @HappyKeyboard: Thanks, I'll take a look at std::initializer_list. Also good to know about the need for double curly brackets with std::array and gcc! Commented Nov 27, 2018 at 4:39

3 Answers 3

4

You can use a variadic template:

#include <array>

struct foo
{
    const std::array<int, 10> bar;

    template<typename... T>
    foo(T&&... t)
    : bar({ std::move(t)... })
    {}
};

int main()
{
    foo f{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
}

Or you can initialize it with an array passed to the constructor:

#include <array>

struct foo
{
    const std::array<int, 10> bar;

    explicit foo(std::array<int, 10> const &qux)
    : bar{ qux }
    {}
};

int main()
{
    std::array<int, 10> qux;
    foo f(qux);
}

But these options don't take into account that you want to have an array of SomeOtherType converted to an array of SomeType. I didn't realize that at first, hece the variants above.

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

struct SomeOtherType{};

struct SomeType {
    SomeType(SomeOtherType) {}
};

struct MyClass
{
    const std::array<SomeType, 100> myArray;

    template<typename T, std::size_t... N>
    MyClass(T&& qux, std::index_sequence<N...>)
    : myArray{ qux[N]... }
    {}

    explicit MyClass(std::array<SomeOtherType, 100> const &qux)
    : MyClass{ qux, std::make_index_sequence<100>{} }
    {}
};

int main()
{
    std::array<SomeOtherType, 100> qux{};
    MyClass foo(qux);
}
Sign up to request clarification or add additional context in comments.

Comments

1

You can unpack arguments with std::index_sequence and delegating constructors

template<typename Arr, size_t... Is>
MyClass(Arr&& arr, std::index_sequence<Is...>)
  : myArray{arr[Is]...} ()

explicit MyClass(std::array<SomeOtherType, 100> arr) : MyClass(arr, std::make_index_sequence<100>{}) ()

Comments

0

This is possible. You just need a little helper function template to do the conversion for you. Something like this:

template <class T, class U, size_t N>
std::array<T, N> ArrayConvert(std::array<U, N> const& init)
{
  std::array<T, N> result;
  std::copy(init.begin(), init.end(), result.begin());
  return result;
}

class Foo
{
  std::array<int, 100> myArray;
public:
  template <class U> Foo(std::array<U, 100> const& init)
    : myArray(ArrayConvert<int>(init))
  {
  }
};

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.