When defining variables and objects they may immediately be given
initial values. Class type objects are always initialized by one of their
available constructors. bf(C) already supports the array and struct
 hi(initialization)emi(initializer list) consisting of a list of constant
expressions surrounded by a pair of curly braces.

bf(C++) supports a comparable initialization, called 
    emi(uniform initialization). It uses the following syntax:
        verb(    Type object{ value list };)

When defining objects using a list of objects each individual object
may use its own uniform initialization.

The advantage of uniform initialization over using constructors is that using
constructor arguments sometimes results in an ambiguity as constructing an
object may sometimes be confused with using the object's overloaded function
call operator (cf. section ref(FUNOBJ)). As initializer lists can only be used
with em(plain old data) (POD) types (cf. section ref(POD)) and with classes
that are `initializer list aware' (like tt(std::vector)) the ambiguity does
not arise when initializer lists are used.

Uniform initialization can be used to initialize an object or variable, but
also to initialize data members in a constructor or implicitly in the return
statement of functions. Examples (in-class implementations for brevity):
        verb(    class Person
    {
        // data members
        public:
            Person(std::string const &name, size_t mass)
            :
                d_name {name},
                d_mass {mass}
            {}

            Person copy() const
            {
                return {d_name, d_mass};
            }
    };)

Object definitions may be encountered in unexpected places, easily resulting in
(human) confusion. Consider a function `tt(func)' and a very simple
class tt(Fun) (tt(struct) is used, as data hiding is not an issue here):
        verb(    void func();

    struct Fun
    {
        Fun(void (*f)())
        {
            std::cout << "Constructor\n";
        };

        void process()
        {
            std::cout << "process\n";
        }
    };)

Assume that in tt(main) a tt(Fun) object is defined as follows: 
        verb(    Fun fun(func);)

Running this program displays tt(Constructor), confirming that the object
tt(fun) is constructed. Next we change this line of code, calling tt(process)
from an anonymous tt(Fun) object:
        verb(    Fun(func).process();)

As expected, tt(Constructor) appears, followed by the text tt(process).

    What about merely defining an anonymous tt(Fun) object? We do:
        verb(    Fun(func);)

Now we're in for a surprise. The compiler complains that tt(Fun)'s default
constructor is missing. Why's that? Insert a blank immediately after
tt(Fun) and you get tt(Fun (func)). Parentheses around an identifier are OK,
and are removed while the parenthesized expression is parsed. In
this case: tt((func)) equals tt(func), and so we have tt(Fun func): the
definition of a tt(Fun func) object, using tt(Fun)'s default constructor (which
isn't declared in tt(Fun's) class interface).

So why does tt(Fun(func).process()) compile? In this case we have a member
selector operator, whose left-hand operand must be an class-type object. The
object must exist, and tt(Fun(func)) represents that object. It's not the name
of an existing object, but a constructor expecting a function (like tt(func))
as its argument. So the compiler creates an em(anonymous) tt(Fun) object,
which receives tt(func) as its argument.

Clearly, with tt(Fun(func)) parentheses cannot be used to create an anonymous
tt(Fun) object. However, a uniform initialization em(can) be used. To define
the anonymous tt(Fun) object we use this syntax:
        verb(    Fun{ func };)

(which can also be used to immediately call one of its members. E.g.,
tt(Fun{ func }.process())).


Although the uniform intialization syntax is slightly different from the
syntax  of an initializer list (the latter using the assignment operator) the
compiler nevertheless uses the initializer list if a constructor
supporting an initializer list is available. As an example consider:
        verb(    class Vector
    {
        public:
            Vector(size_t size);
            Vector(std::initializer_list<int> const &values);
    };

    Vector vi = {4};)

When defining tt(vi) the constructor expecting the initializer list is
called rather than the constructor expecting a tt(size_t) argument. If the
latter constructor is required the standard constructor
syntax must be used. I.e., tt(Vector vi(4)).

    Initializer lists are themselves objects that may be constructed using
another initializer list. However, values stored in an initializer list are
immutable. Once the initializer list has been defined their values remain
as-is.

Initializer lists support a basic set of member functions and constructors:
    itemization(
    ithtq(initializer_list)(initializer_list<Type> object)
        (defines tt(object) as an empty initializer list)
    ittq(initializer_list<Type> object { list of Type values })
        (defines tt(object) as an initializer list containing tt(Type) values)
    ittq(initializer_list<Type> object(other))
        (initializes tt(object) using the values stored in tt(other))
    ithtq(size)(size_t size() const)
        (returns the number of elements in the initializer list)
    ithtq(begin)(Type const *begin() const)
        (returns a pointer to the first element of the initializer list)
    ithtq(end)(Type const *end() const)
        (returns a pointer just beyond the location of the last element of the
initializer list)
    )
