ryan
ryan

Reputation: 3

C++ Initializing a template array in a contructor initializer list

I have a component class that doesn't have a default constructor and needs an object passed to it instead. I want to have a template class that builds a stack space, arbitrarily sized array of this component. Because it doesn't and really shouldn't have a default constructor, I'm running into issues making it work. Another note on the template class is that it can only have one parameter passed to it, and it must use it to initialize all of the array's elements.

Relevant parts of the component I want to create the array of.

class CSomeComponent : public CComponent {
public:
    CSomeComponent(const IObject* pObject) : CComponent(pObject) {
    }
};

Relevant parts of the template array I'm trying to make work.

template<size_t _Count>
class CComponentArray {
public:
    CComponentArray(const IObject* pObject) : m_component(...) {
    }

private:
    CSomeComponent m_component[_Count];
};

I can't change the fact that components don't have a default constructor. I also can't give the component array template more than one parameter. These two constraints are why I can't figure out how I'd do this, so hopefully someone else can. Thank you!

Upvotes: 0

Views: 91

Answers (1)

bolov
bolov

Reputation: 75874

Use std::array and then you can make a constexpr function that initializes and returns the array:

namespace details
{
template <class T, std::size_t Size, class... Args, std::size_t... I>
constexpr auto make_arr_emplace_impl(std::index_sequence<I...>, Args&&... args)
    -> std::array<T, Size>
{
    return std::array<T, Size> {(I, T{args...})...};
}
}


/* creates an std::array<T, Size> where each element is created by calling `T{args...}`
 * note: args will not be moved
 * forwarding references used for preserving constness and binding to temporaries
*/
template <class T, std::size_t Size, class... Args>
constexpr auto make_arr_emplace(Args&&... args) -> std::array<T, Size>
{
    return details::make_arr_emplace_impl<T, Size>(std::make_index_sequence<Size>{}, args...);
}
template<size_t Count>
class CComponentArray {
public:
    CComponentArray(const IObject* pObject)
        : m_component{make_arr_emplace<CSomeComponent, Count>(pObject)}
    {
    }

private:
    std::array<CSomeComponent, Count> m_component;
};

Please note that identifiers starting with double underscore or one underscore and a capital letter - like your _Count - are reserved for implementation.

Upvotes: 1

Related Questions