# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>
# SPDX-FileContributor: 2003-23 Bradley M. Bell
# ----------------------------------------------------------------------------

/*
{xrst_begin SimpleVector}
{xrst_spell
   valarray
}

C++ Concept: A Simple Vector
############################

Template Class Requirements
***************************
A simple vector template class *SimpleVector* ,
is any template class
that satisfies the requirements below.
The following is a list of some simple vector template classes:

.. list-table::
   :widths: auto

   * - **Name**
     - **Documentation**
   * - ``std::vector``
     - Section 16.3 of
       :ref:`Bib@The C++ Programming Language`
   * - ``std::valarray``
     - Section 22.4 of
       :ref:`Bib@The C++ Programming Language`
   * - ``CppAD::vector``
     - :ref:`CppAD_vector-title`

Elements of Specified Type
**************************
A simple vector class with elements of type *Scalar* ,
is any class that satisfies the requirements for a class of the form

   *SimpleVector* < *Scalar* >

The routine :ref:`CheckSimpleVector-name` can be used to check
that a class is a simple vector class with a specified element type.

Default Constructor
*******************
The syntax

   *SimpleVector* < *Scalar* > *x* ;

creates an empty vector *x* ( *x* . ``size`` () is zero)
that can later contain elements of the specified type
(see :ref:`SimpleVector@resize` below).

Sizing Constructor
******************
If *n* has type ``size_t`` ,

   *SimpleVector* < *Scalar* > *x* ( *n* )

creates a vector *x* with *n* elements
each of the specified type.

Copy Constructor
****************
If *x* is a *SimpleVector* < *Scalar* > object,

   *SimpleVector* < *Scalar* > *y* ( *x* )

creates a vector with the same type and number of elements
as *x* .
The *Scalar* assignment operator ( ``=`` )
is used to set each element of *y*
equal to the corresponding element of *x* .
This is a `deep copy' in that the values of the elements
of *x* and *y* can be set independently after the copy.
The argument *x* is passed by reference
and may be ``const`` .

Element Constructor and Destructor
**********************************
The default constructor for type *Scalar* is called
for every element in a vector when the vector element is created.
The *Scalar* destructor is called when it is removed
from the vector (this includes when the vector is destroyed).

Assignment
**********
If *x* and *y* are
*SimpleVector* < *Scalar* > objects,

   *y* = *x*

uses the *Scalar* assignment operator ( ``=`` )
to set each element of *y* equal to
the corresponding element of *x* .
This is a `deep assignment' in that the values of the elements
of *x* and *y* can be set independently after the assignment.
The vectors *x* and *y* must have
the same number of elements.
The argument *x* is passed by reference
and may be ``const`` .

The type returned by this assignment is unspecified; for example,
it might be void in which case the syntax

   *z* = *y* = *x*

would not be valid.

size
****
If *x* is a *SimpleVector* < *Scalar* > object
and ``n`` has type ``size_t`` ,

   *n* = ``size_t`` ( *x* . ``size`` () )

sets *n* to the number of elements in the vector *x* .
The object *x* may be ``const`` .

resize
******
If *x* is a *SimpleVector* < *Scalar* > object
and ``n`` has type ``size_t`` ,

   *x* . ``resize`` ( *n* )

changes the number of elements contained in the vector *x*
to be *n* .
The value of the elements of *x*
are not specified after this operation; i.e.,
any values previously stored in *x* are lost.
(The object *x* can not be ``const`` .)

value_type
**********
If *Vector* is any simple vector class,
the syntax

   *Vector* :: ``value_type``

is the type of the elements corresponding to the vector class; i.e.,

   *SimpleVector* < *Scalar* >:: ``value_type``

is equal to *Scalar* .

Element Access
**************
If *x* is a *SimpleVector* < *Scalar* > object
and *i* has type ``size_t`` ,

   *x* [ *i* ]

returns an object of an unspecified type,
referred to here as *elementType* .

Using Value
===========
If *elementType* is not the same as *Scalar* ,
the conversion operator

   ``static_cast`` < *Scalar* >( *x* [ *i* ])

is used implicitly when *x* [ *i* ] is used in an expression
with values of type *Scalar* .
For this type of usage, the object *x* may be ``const`` .

Assignment
==========
If *y* is an object of type *Scalar* ,

   *x* [ *i* ] = *y*

assigns the *i*-th element of *x* to have value *y* .
For this type of usage, the object *x* can not be ``const`` .
The type returned by this assignment is unspecified; for example,
it might be void in which case the syntax

   *z* = *x* [ *i* ] = *y*

would not be valid.

Example
*******
{xrst_toc_hidden
   example/utility/simple_vector.cpp
}
The file
:ref:`simple_vector.cpp-name`
contains an example and test of a Simple template class.
(It is easy to modify to test additional simple vector template classes.)

Exercise
********

#. If *Vector* is a simple vector template class,
   the following code may not be valid:

   | |tab| *Vector* < ``double> x`` (2);
   | |tab| ``x`` [2] = 1.;

   Create and run a program that executes the code segment
   above where *Vector* is each of the following cases:
   ``std::vector`` ,
   ``CppAD::vector`` .
   Do this both where the compiler option
   ``-DNDEBUG`` is and is not present on the compilation command line.
#. If *Vector* is a simple vector template class,
   the following code may not be valid:

   | |tab| *Vector* < ``int> x`` (2);
   | |tab| *Vector* < ``int> y`` (1);
   | |tab| ``x`` [0] = 0;
   | |tab| ``x`` [1] = 1;
   | |tab| ``y`` = ``x`` ;

   Create and run a program that executes the code segment
   above where *Vector* is each of the following cases:
   ``std::valarray`` ,
   ``CppAD::vector`` .
   Do this both where the compiler option
   ``-DNDEBUG`` is and is not present on the compilation command line.

{xrst_end SimpleVector}
