1

I am new to C++ and I have a question. Let's say I have a class, function definitions and a main so done ( here the source):

// sequence template
#include <iostream>
using namespace std;

template <class T, int N>
class mysequence {
    T memblock [N];
  public:
    void setmember (int x, T value);
    T getmember (int x);
};

template <class T, int N>
void mysequence<T,N>::setmember (int x, T value) {
  memblock[x]=value;
}

template <class T, int N>
T mysequence<T,N>::getmember (int x) {
  return memblock[x];
}

int main () {
  mysequence <int,5> myints;
  mysequence <double,5> myfloats;
  myints.setmember (0,100);
  myfloats.setmember (3,3.1416);
  cout << myints.getmember(0) << '\n';
  cout << myfloats.getmember(3) << '\n';
  return 0;
}

The question is: in the template <class T, int N>, should the value N be known at compile time (like in this case)? Or can be specified at runtime?

Leos313
  • 5,152
  • 6
  • 40
  • 69
  • 6
    It cannot be specified at runtime. Templates only work at compile time. If you need to specify `N` at runtime then you probably should refactor the code so that it accepts `N` as a non-template parameter. – freakish May 13 '18 at 10:50
  • Templates aside, `T memblock [N];` isn't valid with a runtime N. – chris May 13 '18 at 10:51
  • 1
    If you are really really *really* desperate to specify values at runtime, see https://stackoverflow.com/questions/2873802/specify-template-parameters-at-runtime. My recommendation, however: don't do that. – hlt May 13 '18 at 10:52
  • @hit I agree it is a bad idea, but not so bad as to use a pre C++11 solution! – Yakk - Adam Nevraumont May 13 '18 at 11:01
  • 1
    A different aside - I wouldn't trust any site using ["oldtutorial"](http://www.cplusplus.com/doc/oldtutorial/templates/) in the path name to teach me modern C++. Also, your sequence is called [`std::array`](http://en.cppreference.com/w/cpp/header/array) while the one with a runtime size is [`std::vector`](http://en.cppreference.com/w/cpp/header/vector). – Bo Persson May 13 '18 at 11:11

1 Answers1

3

Yes. All template parameters need to be known at compile time (anything else will result in a compiler error).

The reason for this is that technically speaking, mysequence<int, 1> and mysequence<int, 2> are completely separate types, generated by the compiler. If the compiler has never seen your N before, how could it generate the types for you?

The fact that the compiler needs to generate each of those types separately is also what forces you to implement templates in the header. Determining parameters at runtime would obviously be even harder to do (you would need to dynamically recompile your code!).


Here is what the C++ standard has to say about template parameters (that are not types):

A template-argument for a non-type template-parameter shall be a converted constant expression of the type of the template-parameter

[temp.arg.nontype]/2

Now what is a converted constant expression?

A converted constant expression of type T is an expression, implicitly converted to type T, where the converted expression is a constant expression
[some restrictions on the conversions that may be applied follow]

[expr.const]/5

So really, it's just a constant expression with some conversions added. The rules for what exactly is a constant expression are somewhat complex ([expr.const]/2), but the standard has a simple summary:

Expressions that satisfy these requirements, assuming that copy elision is performed, are called constant expressions. [ Note: Constant expressions can be evaluated during translation. — end note ]

[expr.const]/1

Evaluated during translation is a fancy term for "the compiler can do it while compiling."


Therefore, non-type template parameters must be known at compile time (and so do type template parameters, although it is harder to construct a scenario where you would want to set type template parameters at runtime)

hlt
  • 6,219
  • 3
  • 23
  • 43