Join the Stack Overflow Community
Stack Overflow is a community of 6.6 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

Essentially I want a template class with an array whose size is a template parameter, to hold constant content.

Something like:

template<size_t S> struct Foo {
    const int bar[S];
    Foo(const int(&par)[S]) : bar(par) {
        cout << "bar size is " << S << endl;
    }
};
auto foo = Foo({1,2,3});

I have been searching and tinkering a bit, and almost have a workaround implemented with an intermediate static method and using std::array:

template<size_t S> struct Baz {
  const array<int,S> qux;
  Baz(const array<int,S>&par) : qux(par) {
    cout << "size is " << S << endl;
  }
};
template<size_t S> Baz<S>
GetBaz(const array<int,S>&in) {
  return Baz<S>(in);
}

int main() {
  auto sample = GetBaz({1,2,3});
  return 0;
}

... Which is already quite some boilerplate, but still the std::array does not seem to get constructed from an initialiser list? :-(

prog.cpp: In function 'int main()':
prog.cpp:27:30: error: no matching function for call to 'GetBaz(<brace-enclosed initializer list>)'
  auto sample = GetBaz({1,2,3});
share|improve this question
    
You cannot do this with built-in array, must use std::array – M.M Mar 26 '16 at 10:10
    
For auto sample = GetBaz({1,2,3}); it fails because you need to specify GetBaz<5> or whatever. Initializer list length is not part of their type. – M.M Mar 26 '16 at 10:11
1  
The code in this answer may help you solve your problem, if you're willing to use GetBaz(1,2,3) without the extra braces – M.M Mar 26 '16 at 10:33
up vote 4 down vote accepted

Post-DR1591 built-in array bound are now deducible from a braced-init-list, so:

template<size_t S> struct Baz {
  const array<int,S> qux;
  Baz(const array<int,S>&par) : qux(par) {
    cout << "size is " << S << endl;
  }
  Baz(const int (&par)[S]) : qux(std::experimental::to_array(par)) {}
};

template<size_t S> Baz<S>
GetBaz(const int (&in)[S]) {
  return Baz<S>(in);
}

std::experimental::to_array creates an std::array from a built-in one. See the linked cppreference page for implementation.

You can go built-in arrays all the way, but it's somewhat more annoying:

template<size_t S> struct Baz {
  const int bar[S]; 

  template<size_t... Is>
  Baz(const int (&par)[S], std::index_sequence<Is...>)
      : bar { par[Is]... } {}

  Baz(const int (&par)[S]) : Baz(par, std::make_index_sequence<S>()) {}
};

template<size_t S> Baz<S>
GetBaz(const int (&in)[S]) {
  return Baz<S>(in);
}
share|improve this answer
    
Thanks, I am not a fan of using experimental but your answer is very clarifying and answers the question. – gatopeich Mar 26 '16 at 17:05
    
BTW, do you know an equivalent with old style arrays? I still don't understand why std::array was added instead of improving what was already there. – gatopeich Mar 26 '16 at 17:07
    
@gatopeich See edit. – T.C. Mar 27 '16 at 4:12

Not sure if I fully understood the questions. Is that what you are trying to achieve?

#include <iostream>
#include <array>

template<size_t S> struct Baz {
    const std::array<int,S> qux;
    Baz(const std::array<int,S>& par) : qux(par) {
        std::cout << "size is " << qux.size() << std::endl;
    }
};

int main() {
    auto sample = Baz<5>({1,2,3}); // size = 5, values = 1, 2, 3, 0, 0
    return 0;
}

Summary:

  1. Use an std::array instead of a raw array.
  2. Specify the template argument, eg: Baz<5>(...). Class template arguments are not deduced.
share|improve this answer
    
Precisely, I want the array size to be inferred :-). I know class template arguments cannot be deduced from constructor, but I am ready to use a static function GetBaz() for that. The issue I cannot solve in an good looking way is passing the initializer list through the intermediate function into the constructor. – gatopeich Mar 26 '16 at 12:40

You can do it with a classic C array, but using a variadic constructor

#include <array>
#include <cstddef>
#include <iostream>

using namespace std;

template <size_t S> struct Foo {
    const int bar[S];
    const std::array<int, S> bar2;

    template <typename ... I>
       Foo (const I & ... i) : bar {i...}, bar2 {{i...}}
    {
      cout << "bar size is " << S << " == " <<
         (sizeof(bar)/sizeof(bar[0])) << " == " << bar2.size() << endl;
    }
};

int main()
 {
   Foo<3>  foo {1,2,3};

   auto  foo2 = Foo<4>{1,2,3,4};

   return 0;
 }
share|improve this answer

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.