2

I'm currently learning about template meta-programming in c++ and stumbled across variable templates. As a fun exercise, I decided to implement compile time static array with following usage -

my_array<1,2,3,4> arr;  // gives an array with 4 members = 1,2,3,4

I've tried several iterations of my attempt, removing syntax errors along the way but now I'm stuck since no compiler gives useful warning. Here's my current code -

#include <iostream>

template<size_t... Enteries>
constexpr size_t my_array[sizeof...(Enteries)] = {Enteries...};

int main() {
    my_array<1,2,3,4,5,6> arr;
}

but currently it gives following error with clang -

static_array.cpp:7:10: error: expected ';' after expression
        my_array<1,2,3,4,5,6> arr;
                ^
                ;
static_array.cpp:7:24: error: use of undeclared identifier 'arr'
        my_array<1,2,3,4,5,6> arr;
                              ^
static_array.cpp:7:2: warning: expression result unused [-Wunused-value]
        my_array<1,2,3,4,5,6> arr;
        ^~~~~~~~~~~~~~~~~~~~~
1 warning and 2 errors generated.

and with gcc -

static_array.cpp: In function ‘int main()’:
static_array.cpp:7:24: error: expected ‘;’ before ‘arr’
  my_array<1,2,3,4,5,6> arr;
                        ^~~
static_array.cpp:7:27: warning: statement has no effect [-Wunused-value]
  my_array<1,2,3,4,5,6> arr;

How should I proceed forward to implement this thing(preferably with variable templates since I know this can be implemented with old struct technique).

1
  • 4
    my_array<1,2,3,4,5,6> is the array. Commented Jun 23, 2017 at 4:42

3 Answers 3

5

As mentioned in the comments to the question, my_array<1,2,3,4,5,6> isn't a type. my_array is a variable template, it has a type you can use once specialized but it is not a type, you cannot use it the way you are doing.
You cannot declare variables having type my_array<1,2,3,4>, but you can use the variable my_array<1,2,3,4>. As an example, do you want to get the N-th element? my_array<1,2,3,4,5,6>[N];.

Sample program:

#include <iostream>

template<size_t... Enteries>
constexpr size_t my_array[sizeof...(Enteries)] = {Enteries...};

int main() {
   std::cout << my_array<1,2,3,4,5,6>[0] << std::endl;
}

Output:

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

Comments

2

Did you mean to make a type?

#include <stdexcept>

template < size_t... Enteries >
class my_array
{
    constexpr static size_t const N = sizeof...(Enteries);
    constexpr static size_t const value[N] = {Enteries...};
public:
    constexpr size_t operator[](size_t idx) const
    {
      if ( idx < N )
        return value[idx];
      else
        throw std::out_of_range("my_array index out of range");;
    }
};

int main() {
    my_array<1,2,3,4,5,6> arr;
    static_assert( arr[0] == 1, "!" );
    static_assert( arr[1] != 5, "!!" );
  //static_assert( arr[9] == 0, "!!!" ); // Does not compile
}

Comments

1

There are a few approaches to compile-time arrays

With constexpr

Just qualify an array with constexpr

constexpr size_t arr[] = {3, 2, 1};

With variable templates

template<size_t... E>
constexpr size_t arr[] = {E...};

This is known as a variable template, arr is the variable, therefore you would use it like one

for(auto i : arr<42, 420, 4200>)
    std::cout << i << std::endl;

Live

With non-type template parameters

This functionality is provided in C++14 already, namely std::integer_sequence. This is not as straightforward as a simple array and is used mostly when you need a parameter pack of numbers

template<typename T, T... I>
void print(std::integer_sequence<T, I...>)
{
    (std::cout << ... << I);  // fold expression from C++1z, parentheses required
}

print(std::integer_sequence<size_t, 1, 2, 3>{});

Live

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.