BDE 4.14.0 Production release
|
Provide a namespace defining nullable value functions.
The bdlat_NullableValueFunctions
namespace
provided in this component defines parameterized functions that expose "nullable" behavior for "nullable" types. See the {bdlat
} package-level documentation for a full description of "nullable" types.
The functions in this namespace allow users to:
makeValue
),manipulateValue
),accessValue
), andisNull
).A type becomes part of the bdlat
"nullable" framework by creating, in the namespace where the type is defined, specializations of the following four (free) function templates:
A type becomes part of the bdlat
"nullable" framework by creating, in the namespace where the type is defined, overloads of the following two (free) functions and two (free) function templates. Note that the placeholder YOUR_TYPE
is not a template argument and should be replaced with the name of the type being plugged into the framework.
The "nullable" type must also define two meta-functions in the bdlat_NullableValueFunctions
namespace:
IsNullableValue
contains a compile-time constant value
that is non-zero if the parameterized TYPE
exposes "nullable" behavior, andValueType
meta-function contains a typedef
Type
that specifies the type of the value that can be stored in the parameterized "nullable" type.Note that bdlb::NullableValue<TYPE>
is already part of the bldat
infrastructure for "nullable" types because this component also provides overloads of the required functions and meta-function specializations.
This section illustrates intended use of this component.
Suppose you had a type whose value could be in a "null" state.
We can now make mine::MyNullableValue
expose "nullable" behavior by implementing the necessary bdlta_NullableValueFunctions
for MyNullableValue
inside the mine
namespace and defining the required meta-functions withing the bdlat_NullableValueFunctions
namespace.
First, we should forward declare all the functions that we will implement inside the mine
namespace:
Then, we will implement these functions. Recall that the two (non-template) functions should be defined in some .cpp
file, unless you choose to make them inline
functions.
Finally, we specialize the IsNullableValue
and ValueType
meta-functions in the bdlat_NullableValueFunctions
namespace for the mine::MyNullableValue
type:
This completes the bdlat
infrastructure for mine::MyNullableValue
and allows the generic software to recognize the type as a nullable abstraction.
The bdlat
"nullable" framework provides a set of fundamental operations common to any "nullable" type. We can build upon these operations to make our own utilities, or use them on our own types that are plugged into the framework, like mine::MyNullableValue
, which we created in {Example 1}. For example, we can use the (fundamental) operations in the bdlat_NullableValueFunctions
namespace to operate on mine::NullableValue
, even though they have no knowledge of that type in particular:
Two of those operations are rather basic. One simply informs whether or not an object is in the null state (the isNull
method). Another sets an object to a default, non-null state (the makeValue
method).
The other two generic methods accomplish their actions via user-supplied functors.
Let us define a generic functor that gives us access to the underlying value of the "nullable" type, if it's not null:
Notice that the above class makes no assumptions about the value being accessed other than it can be copied (in the constructor) and assigned (in the operator).
This functor can be used to fetch the value of our nullable object:
Notice that we did not invoke accessValue
until object
had been set to a non-null state. Doing otherwise would have led to undefined behavior.
Finally, let's define a functor to set the state of a nullable object:
As with the previous functor, this functor has no knowledge of the nullable type to which it will be applied. The only assumption here is that the value (type) of our nullable type can be copy constructed and copy assigned.
Let us use this functor to modify one of our nullable objects:
Creating functor objects for each operation can be tedious and error prone; consequently, those types are often executed via utility functions.
Suppose we want to create utilities for getting and setting the value associated with an arbitrary "nullable" type.
These functors make minimal assumptions of VALUE_TYPE
, merely that it is copy constructable and copy assignable.
Now, we can use these functors to write generic utility functions for getting and setting the value types of arbitrary "nullable" classes.
Finally, suppose we have another type such as your::YourNullableType
, shown below:
Notice that while there are many similarities to mine::MyNullableValue
there are clearly differences:
bsl::string
, not int
.Nevertheless, since your::YourNullableValue
also provides the functions and types expected by the bdlat
infrastructure (not shown) we can successfully use your::YourNullableValue
value instead of mine::MyNullableValue
in the previous usage scenario, with no other changes:
Notice that syntax and order of bdlat_NullableValueFunction
functions calls have not been changed. The only difference is that the contained type has changed from int
to bsl::string
.
Finally, instead of defining a new "nullable" type, we could substitute the existing type template bdlb::NullableValue
. Note that this component provides specializations of the bdlat_nullableValueFunctions
for that type. Since the accessor and manipulator functions we created earlier are type neutral, we can simply drop bdlb::NullableValue<float>
into our familiar scenario: