13.4 — Template non-type parameters

In previous lessons, you’ve learned how to use template type parameters to create functions and classes that are type independent. However, template type parameters are not the only type of template parameters available. Template classes and functions can make use of another kind of template parameter known as a non-type parameter.

Non-type parameters

A template non-type parameter is a special type of parameter that does not substitute for a type, but is instead replaced by a value. A non-type parameter can be any of the following:

  • A value that has an integral type or enumeration
  • A pointer or reference to a class object
  • A pointer or reference to a function
  • A pointer or reference to a class member function
  • std::nullptr_t

In the following example, we create a non-dynamic (static) array class that uses both a type parameter and a non-type parameter. The type parameter controls the data type of the static array, and the non-type parameter controls how large the static array is.

This code produces the following:

11 10 9 8 7 6 5 4 3 2 1 0
4.4 4.5 4.6 4.7

One noteworthy thing about the above example is that we do not have to dynamically allocate the m_array member variable! This is because for any given instance of the StaticArray class, size is actually constant. For example, if you instantiate a StaticArray<int, 12>, the compiler replaces size with 12. Thus m_array is of type int[12], which can be allocated statically.

This functionality is used by the standard library class std::array. When you allocate a std::array<int, 5>, the int is a type parameter, and the 5 is a non-type parameter!

13.5 -- Function template specialization
13.3 -- Template classes

37 comments to 13.4 — Template non-type parameters

  • Gio

    When compiler encounters a call to the templated classes:

    Does compiler creates two instance of the class StaticArray one for 12 integers array and second for 5 integers array?

      • Gio

        How does compiler distinguishes these created two class instances with the same name?
        Let`s say we have a templated class:

        Than compiler encounters a call to the templated classes:

        After that compiler stencils out a copy of two class instances with the same class names:

        But compiler doesn`t throws the 'class' type redefinition error.

  • sam

    Typo (an instead of a): "a type parameter and an non-type parameter..." --> "a type parameter and a non type parameter..."

    Also in a comment within the code snippet: "for a class with an non-type parameter..." --> "for a class with a non-type parameter...".

  • Xarxos

    Hi, thanks for the lesson! I was just wondering about the utility of this. I understand that it allows us to design classes using a static array without having to rely on dynamic memory, but is that the only advantage? In many situations it seems you could achieve the same result by using a regular parameter in a constructor, so are there any other general cases where a non-type parameter is advantageous?

  • Val

    "Template classes (not template functions) can make use of another kind of template parameter known as an expression parameter."

    Why "not template functions"?

    class Grade:

    Function template:

    Main function:

    Looks like all work!
    As usual, thanks a lot!

    • Alex

      I'm not sure, it does appear to work just fine, and I can't find any documentation to support otherwise. I've updated the lesson accordingly. Thanks for pointing this out.

  • Omri

    "...if you instantiate *an* StaticArray<int, 12>..."
    "...if you instantiate *a* StaticArray<int, 12>..."

  • Curiosity

    An expression parameter can be any of the following :-
    •A pointer or reference to a class object
    •A pointer or reference to a function
    •A pointer or reference to a class member function

    Can u please give an example of each of them ?
    Thanks In Advance

    • Alex

      I could, but I'm not going to for several reasons:
      1) Finding concise examples using these types of expression parameters is challenging
      2) These are almost never used
      3) You should be able to figure this out yourself. 🙂 (just replace the "int" in the template definition with a pointer or reference to a class, function, or member function)

  • Chris

    Hey Alex.

    Would there be a way to have the user input a custom value for the size of the array?
    Doing something like this:

    int main()
        std::cout << "Size of array = ";
        int x;
            std::cin >> x;
            if (
                std::cin.ignore(32767, '\n');
                x = -1;
        } while (x <= 0);
        StaticArray<int, x> intArray;

    results in an error due to x being non-const.

    Is there a way to fix this?


  • Mike

    You mentioned "When you allocate a std::array, the int is a type parameter, and the 5 is an expression parameter!"
    What do you mean by the 5? I'm taking this to assume something like this:

  • Mauricio Mirabetti

    Alex, I believe there's a typo on two places:

    11 10 9 8 7 6 5 4 3 2 1 0
    4.4 4.5 4.6 4.7
    Hello there! // perhaps a left over of an old version example?

    Best regards.

  • Vivian

    Hi Alex,

    Since the example could be rewritten with a constructor to create m_array, how do you decide which would be appropriate (i.e. when would you use a template expression and when would you use a constructor)?


    • Alex

      Generally, template expression parameters are a good choice when you can live with static memory allocation (e.g. arrays that are sized at compile time). Having the constructor create m_array requires dynamic memory allocation, which adds complexity (but also allows other things such as dynamic resizing and the memory comes from the heap instead of the stack, which is beneficial for large arrays).

      So it's really just a matter of tradeoffs.

  • Matt

    Under section "Expression parameters", in the code example, you wrote a comment:
    "// declare an integer buffer with room for 12 chars".

    Did you mean to write "12 integers"?

    Also, in the same code example, towards the end of main(), you used function strcpy_s() to copy the string into your buffer. You may or may not have gone over the use of this function in a previous lesson(I can't recall), and it's easy enough to look it up online(which I had to do), but I think a comment in the code explaining it's use would be very helpful, even though it's fairly obvious what the function is accomplishing. Also, what header file needs to be included to use this function?

    • Alex

      Yes, 12 integers. I updated the comment about strcpy_s -- but I'll clarify further when I rewrite this lesson. I used to cover strcpy_s in earlier lessons but have largely deprecated discussion of working with C-style strings in favor of using std::string. I'll have to figure out how to resolve (either recover that content prior to this lesson, or update this lesson with a different example).

      Thanks for pointing that out.

  • Dave

    #include <cstdlib>
    #include <iostream>
    #include <string>

    template <typename T, int nSize> // nSize is the expression parameter
    class Buffer
        // The expression parameter controls the size of the array
        T m_atBuffer[nSize];

        T* GetBuffer() { return m_atBuffer; }
        T& operator[](int nIndex)
            return m_atBuffer[nIndex];

    template<int nSize>
    void PrintBufferString(Buffer<char, nSize> &rcBuf)
    std::cout << rcBuf.GetBuffer() << std::endl;

    int main()
        // declare an integer buffer with room for 12 chars
        Buffer<int, 12> cIntBuffer;

        // Fill it up in order, then print it backwards
        for (int nCount=0; nCount < 12; nCount++)
            cIntBuffer[nCount] = nCount;

        for (int nCount=11; nCount >= 0; nCount--)
            std::cout << cIntBuffer[nCount] << " ";
        std::cout << std::endl;

        // declare a char buffer with room for 31 chars
        Buffer<char, 31> cCharBuffer;

        // strcpy a string into the buffer and print it
        strcpy_s(cCharBuffer.GetBuffer(), 31, "Hello there!");
        std::cout << cCharBuffer.GetBuffer() << std::endl;

        return 0;

    I tried to compile this, but it says strcpy_s was not declared in this scope. I use netbeans. What am I missing? I've tried using cstring as well.

  • SJ

    Hi Alex,

    Regarding the following:

    "One noteworthy thing about the above example is that we do not have to dynamically allocate the m_atBuffer member array! This is because for any given instance of the Buffer class, nSize is actually constant. For example, if you instantiate a Buffer, the compiler replaces nSize with 12. Thus m_atBuffer is of type int[12], which can be allocated statically."

    Since we are not dynamically allocating the array, does that mean it is being declared on the stack?

  • Kiran C K

    I have a couple of questions:

    1) In the first example, there are no constructors, so how can cIntBuffer assign its value to m_atBuffer?

    2) m_atBuffer is a private member. So, shouldn't that cause a "m_atBuffer is private" error when it is instantiated in main() as above?

    3) Reference must be initiated in the same line. Can we just do that inside the template parameter declaration, if we use reference as expression parameter?

    • Alex

      1) There is no assignment. When the template class is instantiated by cIntBuffer (with nSize=12), all instances of nSize in the class are textually replaced with the value 12, which is then compiled in. This is why we're able to treat it as a compile-time constant.
      2) No. We instantiate cIntBuffer in main(). Because we don't have any constructors, C++ creates an empty default constructor and calls that, which does nothing. So the array m_atBuffer (of type int and size 12) is actually uninitialized to start.
      3) I'm not actually sure. Try it and see if it works. 🙂

      • Kiran C K

        I tried. It shows 2 errors at multiple lines wherever I have used the template. I have used the reference as the second argument

        1)template argument 2 is invalid
        2)'Print' is not a member function

  • JaSoN

    When I try to do this : T& GetBuffer() { return m_atBuffer; }, the compiler report an error. So can you tell me why we use T* GetBuffer() { return m_atBuffer; }? Thank you !!

    • Alex

      In this case, T is of type int, and m_atBuffer is an array of integers. This function returns a pointer to the integer array.

      If you return an element of type T&, then you're trying to return an reference to a single integer, which doesn't make sense in this context.

  • Steve

    Well Alex, there are tons of comments of gratitude but I would like to thank you as well. Great, straightforward tutorial to get us newbies through the basics with spot-on examples. I would like to ask you three things.
    1. Do you have plans on releasing these tutorials as a book. If so, are you going to get a more in-depth look on the standart library as your examples seem to be superior than those in other books. You put a great deal of thought in delivering examples understandable for everyone.
    2. Are you going to get a lesson or two on binary trees and linked lists? Those are particularly interesting.
    3. Is it possible to give a tutorial on game developing including either SDL, OpenGl or Direct3D just to get us through the basic idea of a game structure. This question comes from some examples you have on games and random number generation.
    Thank you.

    • Alex

      1) No, but I'd like to eventually write more tutorials on the standard library functionality.
      2) I'd like to also write some lessons on data structures.
      3) I'd also like to write some basic lessons on SDL and OpenGL.

      The problem is simply one of time. I spend a good part of my limited time answering questions instead of writing articles. Maybe I should focus more on a new content...

  • Sean

    I just finished your awesome tutorial, I felt my understanding to C++ really improved a lot.
    Would you please recommand a couple of C++ books because I really want to keep all the learnings up and may dig more into it?
    I am a VBA programmer for a while and want to be involved in C++ programming work. I think the only way to improve C++ programming skill is to do the real world programming. I am not a CS major. Is there any tests that can tell employers my C++ level and help me land with some entry level C++ programmer?

    Thanks a lot,


    • I'm not really sure what to recommend to you bookwise, as you'll find a lot of books are rather redundant with this tutorial. Instead, I would highly advise assigning yourself a project that will test your skills and make you put the concepts you've learned into play. You'll learn more from doing that than anything at this point.

      I do not know of any standardized C++ proficiency tests. Many employers have their own versions and will have you take them when you apply (if they like your resume enough).

Leave a Comment

Put all code inside code tags: [code]your code here[/code]