0

This:

constexpr const std::array<int, 3> {{
  0,
  1
}};

compiles OK.

But how to check (in compile-time) that whole array is filled? May be some static_assert?

vladon
  • 8,158
  • 2
  • 47
  • 91
  • What do you mean by "filled"? Do you mean initialized? – TartanLlama Oct 06 '16 at 08:40
  • @TartanLlama Yes, initialized. Check that programmer not forgot to add a value after changing size. – vladon Oct 06 '16 at 08:44
  • 3
    There is no way to test whether an object has been initialized or not, but I think the remaining elements are value-initialized (i.e. zero in your case). (In other words, it works like a vanilla array.) – molbdnilo Oct 06 '16 at 08:44
  • Yeah, unless you'd need to write a wrapper function to make the array for you; you can't tell after-the-fact. – TartanLlama Oct 06 '16 at 08:46

2 Answers2

1

You could write a wrapper to generate the array for you and carry out the check:

template <typename T, std::size_t N, typename... Ts>
std::array<T, N> make_array (Ts&&... ts) {
    static_assert(N == sizeof...(Ts), "Must supply N arguments");
    return {{ std::forward<Ts>(ts)... }};   
}

But with that function you may as well just deduce the size of the array from the arguments:

template <typename T, typename... Ts>
std::array<T, sizeof...(Ts)> make_array (Ts&&... ts) {
    return {{ std::forward<Ts>(ts)... }};   
}
TartanLlama
  • 63,752
  • 13
  • 157
  • 193
  • TartanLlama, why I cannot make it constexpr? Clang 3.8.1 says that `non-constexpr function 'forward' cannot be used in a constant expression return {{ std::forward(ts)... }};` ? – vladon Oct 06 '16 at 11:09
  • @vladon `std::forward` is unfortunately not `constexpr` in c++11 (see [here](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3305.html)). If you're just going to use built-in or small types, you could just pass by value, or pass by const ref instead. Alternatively, you could write a `constexpr` forward function. – TartanLlama Oct 06 '16 at 11:13
  • But I use `-std=c++14`... – vladon Oct 06 '16 at 11:18
  • @vladon Hmm, can you post an example? [This](http://coliru.stacked-crooked.com/a/133525bfe3972ba0) seems to work fine. – TartanLlama Oct 06 '16 at 11:20
  • Sorry, it's my bad, somehow I use old libcxx with clang, where std::forward isn't constexpr :( – vladon Oct 06 '16 at 11:33
1

As an enhancement to TartanLlama answer i would wrap the initializing routine into another macro to provide the possibility to create proper documentation and better readability (Since the op mentioned that this is a safety check for other programmers).

template <typename T, T ...ts>
struct ArrayInitializer { 
    const std::array<T, sizeof...(ts)> ARRAY = {{ ts... }}; 
};

/*
 * @document me
 */
#define MAKE_ARRAY(name, ...) \
    constexpr const auto name = ArrayInitializer<int,  ##__VA_ARGS__ >().ARRAY;

// Create array with x elements    
MAKE_ARRAY(arrayName, 1, 2, 3, 4);
hermos
  • 1,338
  • 14
  • 15
  • How is that better than `auto arrayName = make_array(1,2,3,4);` ? (Particularly as `##__VA_ARGS__` is not blessed by the standard.) – Martin Bonner supports Monica Oct 06 '16 at 10:48
  • The way the initialization is done is not in question, since both of the approaches are only used at compile time and serve the same purpose, my point was to provide a readable interface to other programmers that use the array, especially when parsing the sources with doxygen, etc... – hermos Oct 06 '16 at 11:04
  • In fact __VA_ARGS__ is part of the standard. Quote Wikipedia (https://en.wikipedia.org/wiki/Variadic_macro): "Variable-argument macros were introduced in 1999 in the ISO/IEC 9899:1999 (C99) revision of the C language standard, and in 2011 in ISO/IEC 14882:2011 (C++11) revision of the C++ language standard." – hermos Oct 06 '16 at 11:04
  • Yes I know `__VA_ARGS__` is part of the standard - it is preceding it with `##` (the preprocessor token-pasting operator) that is non-standard (although a common extension). – Martin Bonner supports Monica Oct 06 '16 at 11:07
  • 1
    Using a macro for this seems really ugly and unnecessary. What part of that is more readable and documentable than my answer? Even if you've never written a template in your life, `auto arr = make_array(1,2,3);` seems pretty self-documenting to me. – TartanLlama Oct 06 '16 at 11:07