// bdlat_nullablevaluefunctions.h                                     -*-C++-*-

// ----------------------------------------------------------------------------
//                                   NOTICE
//
// This component is not up to date with current BDE coding standards, and
// should not be used as an example for new development.
// ----------------------------------------------------------------------------

#ifndef INCLUDED_BDLAT_NULLABLEVALUEFUNCTIONS
#define INCLUDED_BDLAT_NULLABLEVALUEFUNCTIONS

#include <bsls_ident.h>
BSLS_IDENT("$Id: $")

//@PURPOSE: Provide a namespace defining nullable value functions.
//
//@CLASSES:
//  bdlat_NullableValueFunctions: namespace for "nullable" value functions
//
//@SEE_ALSO: bdlb_nullablevalue
//
//@DESCRIPTION: 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:
//: o make the nullable object contain a value ('makeValue'),
//: o manipulate the value contained in a nullable object using a parameterized
//:   manipulator functor ('manipulateValue'),
//: o access the value contained in a nullable object using a parameterized
//:   accessor functor ('accessValue'), and
//: o check whether the nullable object is null or not ('isNull').
//
// 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.
//..
//  // MANIPULATORS
//  void bdlat_nullableValueMakeValue(YOUR_TYPE *object);
//      // Assign to the specified "nullable" 'object' the default value for
//      // the contained type (i.e., 'ValueType()').
//
//  template <class MANIPULATOR>
//  int bdlat_nullableValueManipulateValue(YOUR_TYPE    *object,
//                                         MANIPULATOR&  manipulator);
//      // Invoke the specified 'manipulator' on the address of the value
//      // stored in the specified "nullable" 'object'.  Return the value from
//      // the invocation of 'manipulator'.  The behavior is undefined if
//      // 'object' contains a null value.
//
//  // ACCESSORS
//  template <class ACCESSOR>
//  int bdlat_nullableValueAccessValue(const YOUR_TYPE& object,
//                                     ACCESSOR&        accessor);
//      // Invoke the specified 'accessor' on a 'const'-reference to the value
//      // stored in the specified "nullable" 'object'.  Return the value from
//      // the invocation of 'accessor'.  The behavior is undefined if 'object'
//      // contains a null value.
//
//  bool bdlat_nullableValueIsNull(const YOUR_TYPE& object);
//      // Return 'true' if the specified "nullable" 'object' contains a null
//      // value, and 'false' otherwise.
//..
// The "nullable" type must also define two meta-functions in the
// 'bdlat_NullableValueFunctions' namespace:
//
//: o the meta-function 'IsNullableValue' contains a compile-time constant
//:   'VALUE' that is non-zero if the parameterized 'TYPE' exposes "nullable"
//:   behavior, and
//:
//: o the 'ValueType' 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.
//
///Usage
//------
// The following code illustrate the usage of this component.
//
///Example 1: Defining a "Nullable" Type
// - - - - - - - - - - - - - - - - - - -
// Suppose you had a type whose value could be in a "null" state.
//
//..
//  namespace BloombergLP {
//  namespace mine {
//
//  struct MyNullableValue {
//
//      // DATA
//      bool d_isNull;
//      int  d_value;
//
//      // CREATORS
//      MyNullableValue()
//      {
//          d_isNull = true;
//      }
//  };
//
//  }  // close namespace mine
//  }  // close enterprise namespace
//..
// 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:
//..
//  namespace BloombergLP {
//  namespace mine {
//
//  // MANIPULATORS
//  void bdlat_nullableValueMakeValue(MyNullableValue *object);
//      // Assign to the specified "nullable" 'object' the default value for
//      // the contained type (i.e., 'ValueType()').
//
//  template <class MANIPULATOR>
//  int bdlat_nullableValueManipulateValue(MyNullableValue *object,
//                                         MANIPULATOR&     manipulator);
//      // Invoke the specified 'manipulator' on the address of the value
//      // stored in the specified "nullable" 'object'.  Return the value from
//      // the invocation of 'manipulator'.  The behavior is undefined if
//      // 'object' contains a null value.
//
//  // ACCESSORS
//  template <class ACCESSOR>
//  int bdlat_nullableValueAccessValue(const MyNullableValue& object,
//                                     ACCESSOR&              accessor);
//      // Invoke the specified 'accessor' on a 'const'-reference to the value
//      // stored in the specified "nullable" 'object'.  Return the value from
//      // the invocation of 'accessor'.  The behavior is undefined if 'object'
//      // contains a null value.
//
//  bool bdlat_nullableValueIsNull(const MyNullableValue& object);
//      // Return 'true' if the specified "nullable" 'object' contains a null
//      // value, and 'false' otherwise.
//
//  }  // close namespace mine
//  }  // close enterprise 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.
//..
//  namespace BloombergLP {
//
//  // MANIPULATORS
//  void mine::bdlat_nullableValueMakeValue(MyNullableValue *object)
//  {
//      assert(object);
//
//      object->d_isNull = false;
//      object->d_value  = 0;
//  }
//
//  template <class MANIPULATOR>
//  int mine::bdlat_nullableValueManipulateValue(MyNullableValue *object,
//                                               MANIPULATOR&     manipulator)
//  {
//      assert(object);
//      assert(!object->d_isNull);
//
//      return manipulator(&object->d_value);
//  }
//
//  // ACCESSORS
//  template <class ACCESSOR>
//  int mine::bdlat_nullableValueAccessValue(const MyNullableValue& object,
//                                           ACCESSOR&              accessor)
//  {
//      assert(!object.d_isNull);
//
//      return accessor(object.d_value);
//  }
//
//  bool mine::bdlat_nullableValueIsNull(const MyNullableValue& object)
//  {
//      return object.d_isNull;
//  }
//
//  }  // close enterprise namespace
//..
// Finally, we specialize the 'IsNullableValue' and 'ValueType' meta-functions
// in the 'bdlat_NullableValueFunctions' namespace for the
// 'mine::MyNullableValue' type:
//..
//  namespace BloombergLP {
//  namespace bdlat_NullableValueFunctions {
//
//  // TRAITS
//  template <>
//  struct IsNullableValue<mine::MyNullableValue> {
//      enum { VALUE = 1 };
//  };
//
//  template <>
//  struct ValueType<mine::MyNullableValue> {
//      typedef int Type;
//  };
//
//  }  // close namespace bdlat_NullableValueFunctions
//  }  // close enterprise namespace
//..
// This completes the 'bdlat' infrastructure for 'mine::MyNullableValue' and
// allows the generic software to recognize the type as a nullable abstraction.
//
///Example 2: Using the Infrastructure Via General Methods
///- - - - - - - - - - - - - - - - - - - - - - - - - - - -
// 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).
//..
//  void usageMakeObject()
//  {
//      BSLMF_ASSERT(bdlat_NullableValueFunctions::
//                   IsNullableValue<mine::MyNullableValue>::VALUE);
//
//      mine::MyNullableValue object;
//      assert( bdlat_NullableValueFunctions::isNull(object));
//
//      bdlat_NullableValueFunctions::makeValue(&object);
//      assert(!bdlat_NullableValueFunctions::isNull(object));
//  }
//..
// 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:
//..
//  template <class VALUE_TYPE>
//  class GetValueAccessor {
//
//      // DATA
//      VALUE_TYPE *d_value_p;
//
//    public:
//      // CREATORS
//      explicit GetValueAccessor(VALUE_TYPE *value)
//      : d_value_p(value)
//      {
//      }
//
//      // MANIPULATORS
//      int operator()(const VALUE_TYPE& containedValue)
//          // Assign the value of the specified 'containedValue' to the object
//          // addressed by 'd_value_p'.
//      {
//          *d_value_p = containedValue;
//          return 0;
//      }
//  };
//..
// 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:
//..
//  void usageGetValue()
//  {
//      mine::MyNullableValue object;
//
//      bdlat_NullableValueFunctions::makeValue(&object);
//      assert(!bdlat_NullableValueFunctions::isNull(object));
//
//      int value;
//      GetValueAccessor<int> accessor(&value);
//
//      int rc = bdlat_NullableValueFunctions::accessValue(object, accessor);
//      assert(0 == rc);
//      assert(0 == value);
//  }
//..
// 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:
//..
//  template <class VALUE_TYPE>
//  class SetValueManipulator {
//
//      // DATA
//      VALUE_TYPE d_value;
//
//    public:
//      // CREATORS
//      explicit SetValueManipulator(const VALUE_TYPE& value)
//      : d_value(value)
//      {
//      }
//
//      // ACCESSOR
//      int operator()(VALUE_TYPE *value) const
//      {
//          *value = d_value;
//          return 0;
//      }
//  };
//..
// 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:
//..
//  void usageSetValue()
//  {
//      mine::MyNullableValue object;
//
//      bdlat_NullableValueFunctions::makeValue(&object);
//      assert(!bdlat_NullableValueFunctions::isNull(object));
//
//      SetValueManipulator<int> manipulator(42);
//      int rcm = bdlat_NullableValueFunctions::manipulateValue(&object,
//                                                              manipulator);
//      assert(0 == rcm);
//
//      // Confirm that the object was set to the expected state.
//
//      int value;
//      GetValueAccessor<int> accessor(&value);
//
//      int rca = bdlat_NullableValueFunctions::accessValue(object, accessor);
//      assert( 0 == rca);
//      assert(42 == value);
//  }
//..
//
///Example 3: Defining Utility Functions
///- - - - - - - - - - - - - - - - - - -
// 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.
//
//..
//  struct NullableValueUtil {
//
//      // CLASS METHODS
//      template <class NULLABLE_VALUE_TYPE>
//      static int getValue(
//          typename bdlat_NullableValueFunctions
//                              ::ValueType<NULLABLE_VALUE_TYPE>::Type *value,
//          const NULLABLE_VALUE_TYPE&                                  object)
//          // Load to the specified 'value' the value of the specified
//          // nullable value 'object'.  This function template requires that
//          // the specified 'NULLABLE_VALUE_TYPE' is a 'bdlat' "nullable"
//          // type.  The behavior is undefined unless 'object' is in a
//          // non-null state (i.e.,
//          // 'false == bdlat_NullableValueFunctions::isNull(object))'.
//      {
//          BSLMF_ASSERT(bdlat_NullableValueFunctions
//                              ::IsNullableValue<NULLABLE_VALUE_TYPE>::VALUE);
//
//          BSLS_ASSERT(!bdlat_NullableValueFunctions::isNull(object));
//
//          typedef typename bdlat_NullableValueFunctions
//                            ::ValueType<NULLABLE_VALUE_TYPE>::Type ValueType;
//
//          GetValueAccessor<ValueType> valueAccessor(value);
//          return bdlat_NullableValueFunctions::accessValue(object,
//                                                           valueAccessor);
//      }
//
//      template <class NULLABLE_VALUE_TYPE>
//      static int setValue(NULLABLE_VALUE_TYPE                        *object,
//                          const typename bdlat_NullableValueFunctions
//                             ::ValueType<NULLABLE_VALUE_TYPE>::Type&  value)
//          // Set the value of the specified 'object' to the specified
//          // 'value'.  This function template requires that the specified
//          // 'NULLABLE_VALUE_TYPE' is a 'bdlat' "nullable" type.  The
//          // behavior is undefined unless 'object' is in a non-null state
//          // (i.e., 'false == bdlat_NullableValueFunctions::isNull(object))'.
//          // Note that a "nullable" object can be put into a non-null state
//          // by the 'bdlat_NullableValueFunctions::makeValue' function
//          // overload for the 'NULLABLE_VALUE_TYPE'.
//      {
//          BSLMF_ASSERT(bdlat_NullableValueFunctions
//                              ::IsNullableValue<NULLABLE_VALUE_TYPE>::VALUE);
//
//          BSLS_ASSERT(object);
//          BSLS_ASSERT(!bdlat_NullableValueFunctions::isNull(*object));
//
//          typedef typename bdlat_NullableValueFunctions
//                            ::ValueType<NULLABLE_VALUE_TYPE>::Type ValueType;
//
//          SetValueManipulator<ValueType> manipulator(value);
//          return bdlat_NullableValueFunctions::manipulateValue(object,
//                                                               manipulator);
//      }
//  };
//..
// Now, we can use these functors to write generic utility functions for
// getting and setting the value types of arbitrary "nullable" classes.
//..
//  void myUsageScenario()
//  {
//      mine::MyNullableValue object;
//      assert(bdlat_NullableValueFunctions::isNull(object));
//
//      bdlat_NullableValueFunctions::makeValue(&object);
//      assert(!bdlat_NullableValueFunctions::isNull(object));
//
//      typedef
//      bdlat_NullableValueFunctions::ValueType<mine::MyNullableValue>::Type
//                                                               MyValueType;
//
//      int rcs = NullableValueUtil::setValue(&object, MyValueType(42));
//      assert(0 == rcs);
//
//      MyValueType value;
//      int rcg = NullableValueUtil::getValue(&value, object);
//      assert( 0 == rcg);
//      assert(42 == value);
//  }
//..
//
///Example 4: Achieving Type Independence
/// - - - - - - - - - - - - - - - - - - -
// Finally, suppose we have another type such as 'your::YourNullableType',
// shown below:
//..
//  namespace BloombergLP {
//  namespace your {
//
//  class YourNullableValue {
//
//      // DATA
//      bool        d_isNull;
//      bsl::string d_value;
//
//    public:
//      // CREATORS
//      YourNullableValue()
//      : d_isNull(true)
//      , d_value()
//      {
//      }
//
//      // MANIPULATORS
//      void makeValue()
//      {
//          d_isNull = false;
//          d_value.clear();
//      }
//
//      void makeNull()
//      {
//          d_isNull = true;
//          d_value.clear();
//      }
//
//      bsl::string& value()
//      {
//          assert(!d_isNull);
//
//          return d_value;
//      }
//
//      // ACCESSORS
//      const bsl::string& value() const
//      {
//          assert(!d_isNull);
//
//          return d_value;
//      }
//      bool isNull() const
//      {
//          return d_isNull;
//      }
//  };
//
//  }  // close namespace your
//  }  // close enterprise namespace
//..
// Notice that while there are many similarities to 'mine::MyNullableValue'
// there are clearly differences:
//: o The value type is 'bsl::string', not 'int'.
//: o Attributes are accessed via accessor methods, not public data members.
//
// 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:
//..
//  void yourUsageScenario()
//  {
//      your::YourNullableValue object;  // YOUR NULLABLE TYPE
//      assert(bdlat_NullableValueFunctions::isNull(object));
//
//      bdlat_NullableValueFunctions::makeValue(&object);
//      assert(!bdlat_NullableValueFunctions::isNull(object));
//
//      typedef
//      bdlat_NullableValueFunctions::ValueType<your::YourNullableValue>::Type
//                                                               YourValueType;
//
//      int rcs = NullableValueUtil::setValue(&object, YourValueType("NB"));
//      assert(0 == rcs);
//
//      YourValueType value;
//      int rcg = NullableValueUtil::getValue(&value, object);
//      assert(  0  == rcg);
//      assert("NB" == value);
//  }
//..
// 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:
//..
//  void anotherUsageScenario()
//  {
//      bdlb::NullableValue<float> object;  // BDE NULLABLE TYPE
//      assert(bdlat_NullableValueFunctions::isNull(object));
//
//      bdlat_NullableValueFunctions::makeValue(&object);
//      assert(!bdlat_NullableValueFunctions::isNull(object));
//
//      typedef
//      bdlat_NullableValueFunctions::ValueType<bdlb::NullableValue<float> >
//                                                  ::Type AnotherValueType;
//
//      int rcs = NullableValueUtil::setValue(&object, AnotherValueType(2.0));
//      assert(0 == rcs);
//
//      AnotherValueType value;
//      int rcg = NullableValueUtil::getValue(&value, object);
//      assert(0   == rcg);
//      assert(2.0 == value);
//  }
//..

#include <bdlscm_version.h>

#include <bslmf_metaint.h>

#include <bsls_assert.h>
#include <bsls_review.h>

#include <bdlat_bdeatoverrides.h>

#include <bdlb_nullablevalue.h>
#include <bdlb_nullableallocatedvalue.h>

#include <bslmf_matchanytype.h>

namespace BloombergLP {

                   // ======================================
                   // namespace bdlat_NullableValueFunctions
                   // ======================================

namespace bdlat_NullableValueFunctions {
    // This 'namespace' provides functions that expose "nullable" behavior for
    // "nullable" types.  See the component-level documentation for more
    // information.

    // META-FUNCTIONS
    template <class TYPE>
    struct IsNullableValue {
        // This 'struct' should be specialized for third-party types that need
        // to expose "nullable" behavior.  See the component-level
        // documentation for further information.

        enum {
            VALUE = 0
        };
    };

    template <class TYPE>
    struct ValueType;
        // This meta-function should contain a typedef 'Type' that specifies
        // the type of value stored in a nullable type of the parameterized
        // 'TYPE'.

    // MANIPULATORS
    template <class TYPE>
    void makeValue(TYPE *object);
        // Assign to the specified "nullable" 'object' the default value for
        // the contained type.

    template <class TYPE, class MANIPULATOR>
    int manipulateValue(TYPE         *object,
                        MANIPULATOR&  manipulator);
        // Invoke the specified 'manipulator' on the address of the value
        // stored in the specified "nullable" 'object'.  Return the value from
        // the invocation of 'manipulator'.  The behavior is undefined unless
        // 'object' does not contain a null value.

    // ACCESSORS
    template <class TYPE, class ACCESSOR>
    int accessValue(const TYPE& object,
                    ACCESSOR&   accessor);
        // Invoke the specified 'accessor' on the non-modifiable value stored
        // in the specified "nullable" 'object'.  Return the value from the
        // invocation of 'accessor'.  The behavior is undefined unless 'object'
        // does not contain a null value.

    template <class TYPE>
    bool isNull(const TYPE& object);
        // Return 'true' if the specified "nullable" 'object' contains a null
        // value, and 'false' otherwise.

}  // close namespace bdlat_NullableValueFunctions

                      // ================================
                      // bdlb::NullableValue declarations
                      // ================================

namespace bdlat_NullableValueFunctions {
    // This namespace declaration adds the implementation of the "nullable
    // value" traits for 'bdlb::NullableValue' to
    // 'bdlat_NullableValueFunctions'.  Note that 'bdlb::NullableValue' is the
    // first of two canonical "nullable value" types.

    // META-FUNCTIONS
    template <class TYPE>
    struct IsNullableValue<bdlb::NullableValue<TYPE> > {
        enum {
            VALUE = 1
        };
    };

    template <class TYPE>
    struct ValueType<bdlb::NullableValue<TYPE> > {
        typedef TYPE Type;
    };

    // MANIPULATORS
    template <class TYPE>
    void bdlat_nullableValueMakeValue(bdlb::NullableValue<TYPE> *object);

    template <class TYPE, class MANIPULATOR>
    int bdlat_nullableValueManipulateValue(
                                       bdlb::NullableValue<TYPE> *object,
                                       MANIPULATOR&               manipulator);

    // ACCESSORS
    template <class TYPE, class ACCESSOR>
    int bdlat_nullableValueAccessValue(
                                    const bdlb::NullableValue<TYPE>& object,
                                    ACCESSOR&                        accessor);

    template <class TYPE>
    bool bdlat_nullableValueIsNull(const bdlb::NullableValue<TYPE>& object);

}  // close namespace bdlat_NullableValueFunctions

                  // =========================================
                  // bdlb::NullableAllocatedValue declarations
                  // =========================================

namespace bdlat_NullableValueFunctions {
    // This namespace declaration adds the implementation of the "nullable
    // value" traits for 'bdlb::NullableAllocatedValue' to
    // 'bdlat_NullableValueFunctions'.  Note that
    // 'bdlb::NullableAllocatedValue' is the second of two canonical "nullable
    // value" types.

    // META-FUNCTIONS
    template <class TYPE>
    struct IsNullableValue<bdlb::NullableAllocatedValue<TYPE> > {
        enum {
            VALUE = 1
        };
    };

    template <class TYPE>
    struct ValueType<bdlb::NullableAllocatedValue<TYPE> > {
        typedef TYPE Type;
    };

    // MANIPULATORS
    template <class TYPE>
    void bdlat_nullableValueMakeValue(
                                   bdlb::NullableAllocatedValue<TYPE> *object);

    template <class TYPE, class MANIPULATOR>
    int bdlat_nullableValueManipulateValue(
                              bdlb::NullableAllocatedValue<TYPE> *object,
                              MANIPULATOR&                        manipulator);

    // ACCESSORS
    template <class TYPE, class ACCESSOR>
    int bdlat_nullableValueAccessValue(
                           const bdlb::NullableAllocatedValue<TYPE>& object,
                           ACCESSOR&                                 accessor);

    template <class TYPE>
    bool bdlat_nullableValueIsNull(
                             const bdlb::NullableAllocatedValue<TYPE>& object);

}  // close namespace bdlat_NullableValueFunctions

// ============================================================================
//                            INLINE DEFINITIONS
// ============================================================================

                   // --------------------------------------
                   // namespace bdlat_NullableValueFunctions
                   // --------------------------------------

// MANIPULATORS
template <class TYPE>
inline
void bdlat_NullableValueFunctions::makeValue(TYPE *object)
{
    bdlat_nullableValueMakeValue(object);
}

template <class TYPE, class MANIPULATOR>
inline
int bdlat_NullableValueFunctions::manipulateValue(TYPE         *object,
                                                  MANIPULATOR&  manipulator)
{
    return bdlat_nullableValueManipulateValue(object, manipulator);
}

// ACCESSORS
template <class TYPE, class ACCESSOR>
inline
int bdlat_NullableValueFunctions::accessValue(const TYPE& object,
                                              ACCESSOR&   accessor)
{
    return bdlat_nullableValueAccessValue(object, accessor);
}

template <class TYPE>
inline
bool bdlat_NullableValueFunctions::isNull(const TYPE& object)
{
    return bdlat_nullableValueIsNull(object);
}

                      // -------------------------------
                      // bdlb::NullableValue definitions
                      // -------------------------------

// MANIPULATORS
template <class TYPE>
inline
void bdlat_NullableValueFunctions::bdlat_nullableValueMakeValue(
                                             bdlb::NullableValue<TYPE> *object)
{
    object->makeValue();
}

template <class TYPE, class MANIPULATOR>
inline
int bdlat_NullableValueFunctions::bdlat_nullableValueManipulateValue(
                                        bdlb::NullableValue<TYPE> *object,
                                        MANIPULATOR&               manipulator)
{
    BSLS_ASSERT(!object->isNull());

    return manipulator(&object->value());
}

// ACCESSORS
template <class TYPE, class ACCESSOR>
inline
int bdlat_NullableValueFunctions::bdlat_nullableValueAccessValue(
                                     const bdlb::NullableValue<TYPE>& object,
                                     ACCESSOR&                        accessor)
{
    BSLS_ASSERT(!object.isNull());

    return accessor(object.value());
}

template <class TYPE>
inline
bool bdlat_NullableValueFunctions::bdlat_nullableValueIsNull(
                                       const bdlb::NullableValue<TYPE>& object)
{
    return object.isNull();
}

                  // ----------------------------------------
                  // bdlb::NullableAllocatedValue definitions
                  // ----------------------------------------

// MANIPULATORS
template <class TYPE>
inline
void bdlat_NullableValueFunctions::bdlat_nullableValueMakeValue(
                                    bdlb::NullableAllocatedValue<TYPE> *object)
{
    object->makeValue();
}

template <class TYPE, class MANIPULATOR>
inline
int bdlat_NullableValueFunctions::bdlat_nullableValueManipulateValue(
                               bdlb::NullableAllocatedValue<TYPE> *object,
                               MANIPULATOR&                        manipulator)
{
    BSLS_ASSERT(!object->isNull());

    return manipulator(&object->value());
}

// ACCESSORS
template <class TYPE, class ACCESSOR>
inline
int bdlat_NullableValueFunctions::bdlat_nullableValueAccessValue(
                            const bdlb::NullableAllocatedValue<TYPE>& object,
                            ACCESSOR&                                 accessor)
{
    BSLS_ASSERT(!object.isNull());

    return accessor(object.value());
}

template <class TYPE>
inline
bool bdlat_NullableValueFunctions::bdlat_nullableValueIsNull(
                              const bdlb::NullableAllocatedValue<TYPE>& object)
{
    return object.isNull();
}

}  // close enterprise namespace

#endif

// ----------------------------------------------------------------------------
// Copyright 2015 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------- END-OF-FILE ----------------------------------