7

I have a class template which builds a simple array based on the template parameters as one of its members. I need to be able to initialize every element in the array to a single value in one of the constructors. Unfortunately this constructor must be constexpr.

The relevant part boils down to:

template <typename T, size_t N>
class foo
{
  T data[N];

  constexpr foo(T val)
  {
    // initialize data with N copies of val
  }
};

Using std::fill or a loop is incompatible with the constexpr requirement. Initializing with : data{val} only sets the first element of the array and zero-initializes the remainder.

How can this be achieved?

I feel like there should be a solution with variadic templates and tuples etc...

2
  • @BryanChen: Not so much, that question isn't about constexpr Commented May 28, 2014 at 1:32
  • There's a straightforward way to achieve what you want if constructor argument of "foo(T val)" could be turned into a template argument "template <T val> foo()". Commented May 28, 2014 at 2:37

2 Answers 2

8

Rather curiously, a solution for the problem exists in c++14 (compile the example with -std=c++1y on gcc; also see comments for a bit more verbose c++11 solution by Praetorian):

template <size_t N>
struct bar {
    template <typename T, typename ...Tn>
    static constexpr auto apply(T v, Tn ...vs)
    {
        return bar<N - 1>::apply(v, v, vs...);
    }
};

template <>
struct bar<1> {
    template <typename T, typename ...Tn>
    static constexpr auto apply(T v, Tn ...vs)
    {
        return std::array<T, sizeof...(vs) + 1>{v, vs...};
    }

};

template <typename T, size_t N>
struct foo {
    std::array<T, N> data;

    constexpr foo(T val)
    : data(bar<N>::apply(val))
    {}
};

(I replaced the POD array with std::array - suppose it should not make any problems for your use case).

Live example is here: http://coliru.stacked-crooked.com/a/4731a10ee54563b9

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

2 Comments

+1 Works with -std=c++11 also if you specify the return types for the functions. coliru.stacked-crooked.com/a/668bd7f546654971
Of course - somehow decltype() had slipped my mind.
6

You may use the following: (https://ideone.com/xTacMP)

namespace detail
{
    template <typename T, std::size_t...Is>
    constexpr std::array<T, sizeof...(Is)> make_array(T val, index_sequence<Is...>)
    {
        return {(static_cast<void>(Is), val)...};
    }
}

template <std::size_t N, typename T>
constexpr std::array<T, N> make_array(T val)
{
    return detail::make_array(val, make_index_sequence<N>());
}

And then call it:

constexpr foo(T val) : data(make_array<N>(val)) {}

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.