Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I want to implement a data structure with compile time constant size(like std::array). I want to be able to initialize this data structure like this:

MyStruct<3, int> example = {1, 2, 3};

This work fine using constructor like: MyStruct(std::initializer_list<T> elements), but the compiler doesn't enforce the same size for my internal structure and elements, even if they are both known at compile time.

I can't use static_assert because elements.size() is not compile time constant.

Is there any way to enforce at compile time same size for elements as in MyStruct?

share|improve this question

2 Answers 2

up vote 2 down vote accepted

You could try a constructor using variadic templates:

template<std::size_t N, typename E>
struct MyStruct {
    int otherStuff;
    E values[N];

    template<typename ...TT>
    MyStruct(TT&&...t) : values{std::forward<TT>(t)...} {
        static_assert(N == sizeof...(t), "Size mismatch!");
        for (size_t i = 0; i < N; i++) std::cout << values[i] << ",";
        std::cout << std::endl;
    }
};

This does work as expected with:

MyStruct<3, int> example = {1,2,3};
MyStruct<3, int> exampleFail = {1,2}; //error: static assertion failed: Size mismatch!

Please note that there is still a difference between std:array and MyStruct when it comes to list-initialization:

MyStruct<3, int> exampleList{1,2,3}; // works
std::array<int, 3> arr = {1,2,3};    // works, but warning with clang++
std::array<int, 3> arrList{1,2,3};   // works with g++, does not compile with clang++

The reason is, that the single brace only works for std::array because of brace elision, which does not always apply as documented in an official defect report.

share|improve this answer
    
Very nice, thanks. I already tried this but there is a warning if I add default constructor - multiple default constructors specified(VS2013 preview) –  Felics Jul 31 '13 at 14:23
    
With g++ or clang++ i don't get a warning when I add MyStruct() = default;. You may be able to use some enable_if trickery for that, but I can't come up with something right now that works. This could also allow you to only enable the constructor with the right number of arguments instead of triggering the assertion. See seanmiddleditch.com/journal/2012/03/… –  Zulan Jul 31 '13 at 14:38
    
Yes, std::enable_if will do the trick! Thanks! –  Felics Jul 31 '13 at 14:45

std::array does not have a constructor! And it doesn't use initializer_list, instead it uses uniform initialization. (similar to POD structures, actually std::array is POD structure).

So what std::array really does is very similar to the following:

template<int size, typename T>
struct array {
   T data[size];
   // and some member function here;
   // Warning! No constructors !
};

When, later, you write

std::array<3, int> arr = {1,2,3};

It is equivalent to

std::array<3, int> arr = {{1,2,3}};

And this is just POD initialization where {1,2,3} is assigned to data.


If you want to enforce having the same size checking in compile time it's possible using std::array itself instead of std::initializer_list.

If you change your initializations from {1,2,3} to std::array<3, int>{1, 2, 3} and constructor argument from std::initializer_list<T> to std::array<SIZE, T> user will be enforced to pass array with size SIZE.

share|improve this answer
    
MyStruct has compile time constant size LIKE std::array, it's not std::array. I need contructors to initialize with default values if there are no values provided. –  Felics Jul 31 '13 at 13:52
    
But std::array<3, int> arr = {1,2} does initialize with default value arr[2] although you didn't provide it yourself. arr[2] will be equal to 0 –  sasha.sochka Jul 31 '13 at 13:56
    
But... maybe default value is not 0. Think about a color where I want to use default value 255 or 1.f, depending on color representation. –  Felics Jul 31 '13 at 13:59
    
@Felics, see my update. –  sasha.sochka Jul 31 '13 at 14:09
    
Thanks for the answer. I won't accept it for now - I need to use clasic syntanx to build MyStruct. Using it like this is very confusing. –  Felics Jul 31 '13 at 14:22

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.