Search

13.4 — Template expression 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 (not template functions) can make use of another kind of template parameter known as an expression parameter.

Expression parameters

A template expression parameter is a special type of parameter that does not substitute for a type, but is instead replaced by a value. An expression 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

In the following example, we create a non-dynamic (static) array class that uses both a type parameter and an expression parameter. The type parameter controls the data type of the static array, and the expression 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
Hello there!

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 an StaticArray, 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, the int is a type parameter, and the 5 is an expression parameter!

13.5 -- Function template specialization
Index
13.3 -- Template classes

15 comments to 13.4 — Template expression parameters

  • Sean

    Alex,
    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,

    Sean,

    • 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).

  • 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…

  • 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.

  • 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

  • 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?

  • Dave

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

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

    public:
        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.
    Thanks!

  • 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.

Leave a Comment

Put C++ code inside [code][/code] tags to use the syntax highlighter