(containers)= # C++ Container classes In ROOT and C++, there are a couple of general categories of containers you have to know about. ## Arrays Do a web search on "C++ arrays" to learn about these containers.[^numpy] Briefly, to create a double-precision array of eight elements, you could say: Double_t myArray[8]; [^numpy]: If you're doing these exercises in Python: You'll want to use numpy arrays instead. Fortunately, numpy arrays will automatically be converted to C++ arrays when they're passed as arguments to ROOT methods. To refer to the 3rd element in the array, you might use (remember, in C++ the first element has an index of 0):[^pointer] Int_t i = 2; myArray[i] = 0.05; [^pointer]: If you're new to C++, it won't be obvious that while **`myArray[2]`** is a `Double_t` object, the type of the name **`myArray`** (without any index) is `Double_t*`, or a {ref}`pointer ` to a `Double_t`. Getting confused? Let's keep it simple. If you've created arrays with values and errors... Double_t xValue[22]; Double_t xError[22]; Double_t yValue[22]; Double_t yError[22]; ...and you've put numbers into those arrays, then you can create a `TGraphErrors` object with: auto myPlot = new TGraphErrors(22,xValue,yValue,xError,yError); :::{admonition} Array size :class: note Did you notice a problem with that example? I had to supply a fixed value for the number of points in each array to make the plot. In general, you won't be able to do that; in fact, in subsequent exercises you *can't* do that. In C++, one way to get around this problem is to use "dynamic arrays." I'll let you read about those on the web (search on "C++ dynamic arrays"), but I'm not going to say more about them, because I rarely use them. ::: ## C++ Standard Template Library (STL) Do a web search on "standard template library". Skim a few sites, especially those that contain the words "introduction" or "tutorial". You don't have to get too in-depth; for example, you probably don't have enough time today to fully understand the concept of iterators. :::{admonition} My preference :class: note Did you guess that STL is my preferred method of using containers in C++? The Standard Template Library is an important development in the C++ programming language. It ties into the concepts of design patterns and generic programming, and you can spend a lifetime learning about them.[^joke] ::: [^joke]: You may be tired of the joke, but I'm not! ## Vectors :::{admonition} You only need one :class: note For the work that you'll be asked to do in the {ref}`advanced exercises`, {ref}`expert exercises`, and probably for the rest of this summer, there's only one STL class you'll have to understand: vectors.[^listlike] Here are the basics. ::: [^listlike]: In Python terms, a C++ vector is like a [list](https://www.w3schools.com/python/python_lists.asp) that can contain only one type; you can have a vector of integers or a vector of real numbers, but you can't (easily) have a vector that contains both data types. If you want to use vectors in a program, or even a ROOT macro, you have to put the following near the top of your C++ code: #include To create a vector that will contain a certain type, e.g., double-precision values: std::vector myVector; If you want to create a vector with a fixed number of elements, e.g., 8: std::vector myOtherVector(8); To refer to a specific element of a vector, use the same notation that you use for C++ arrays: myOtherVector[2] = 0.05; The main reason to use vectors for these Exercises is that it's easy to add a new value to the end of a vector.[^hard] To append a value to a vector, use the **`push_back()`** method: myVector.push_back( 0.015 ); [^hard]: Adding a new element to the end of a C++ array is tricky, since arrays are supposed to be of a fixed length. That's why I prefer vectors over arrays. To find out the current length of a vector, use the size() method: Int_t length = myVector.size(); Here's a simple code fragment that loops over the elements of a vector and prints them out. :::{code-block} c++ for ( size_t i = 0; i != someVector.size(); ++i ) { std::cout << "The value of element " << i << " is " << someVector[i] << std::endl; } ::: You have a vector, but TGraphErrors expects C++ arrays. Here's the trick to convert a vector to an array:[^advanced] [^advanced]: *Advanced note:* In other words, if **`v`** has the type **`std::vector`**, then **`v.data()`** is equivalent to the underlying **`Double_t`** array. :::{code-block} c++ // Define four vectors. std::vector x,y,ex,ey; // Put values in the vectors (omitted so you can do it!) // Use .data() to convert the vector to an array. Int_t n = x.size(); TGraphErrors* plot = new TGraphErrors(n, x.data(), y.data(), ex.data(), ey.data()); ::: We're getting closer to being able to tackle the {ref}`first advanced exercise `!