// bdlat_valuetypefunctions.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_VALUETYPEFUNCTIONS
#define INCLUDED_BDLAT_VALUETYPEFUNCTIONS

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

//@PURPOSE: Provide a namespace for "value type" functions.
//
//@CLASSES:
//  bdlat_ValueTypeFunctions: namespace for "value type" functions
//
//@DESCRIPTION: This component provides a 'namespace',
// 'bdlat_ValueTypeFunctions', defining functions that may be called on "value
// types".
//
// The functions in this namespace allow users to:
//
//: o 'assign' values to "value type" objects (ie., as if by using the
//:   assignment operator '*lhs = rhs'), and
//:
//: o 'reset' "value type" objects to their default state (i.e., as if each
//:   object was just constructed using its default constructor).
//
// Types in the 'bdlat' "value type" framework are required to have:
//: o a default constructor
//: o a copy assignment operator
//: o the free function template and the free function described below.
//
// Types in the 'bdlat' "value type" framework must define in the namespace
// where the type is defined, overloads of the following free function template
// and free frunction.  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
//  template <class RHS_TYPE>
//  int bdlat_valueTypeAssign(YOUR_TYPE *lhs, const RHS_TYPE& rhs);
//      // Assign to the specified 'lhs' the value if the specified 'rhs'.
//      // Return 0 on success and a non-zero value otherwise.  If setting
//      // 'lhs' to 'rhs' would violate any preconditions, a non-zero value is
//      // returned.  If (template parameter) 'RHS_TYPE' cannot be used to set
//      // the value of 'lhs', a non-zero value is returned.
//
//  void bdlat_valueTypeReset(YOUR_TYPE *object);
//      // Reset the specified 'object' to that of its default state (i.e., to
//      // 'YOUR_TYPE()').
//..
// Notice that, unlike other 'bdlat' type infrastructures, the 'bdlat' "value"
// infrastructure does *not* require the setting of any traits, or definition
// of meta-functions, or creation of any 'typedef's.  For example, see
// {'bdlat_arrayfunctions'} and {'bdlat_nullablevaluefunctions'}.
//
// There are two significant implications of the contract for
// 'bdlat_valueTypeAssign':
//
//: o Interactions with incompatible types are handled at run-time, not
//:   compile-time.
//:
//: o Users of the 'bdlat_valueTypeAssign' function deal with a wide contract,
//:   even if the corresponding operation in 'YOUR_TYPE' has a narrow contract.
//
///Supported Types
///---------------
// This component provides "value type" support for the following types:
//
//: o All types with a default constructor and copy assignment operator.
//:
//: o Types having any of the following traits (see {'bdlat_typetraits'}):
//:
//:   o 'bdlat_TypeTraitBasicSequence'
//:   o 'bdlat_TypeTraitBasicChoice'
//:   o 'bdlat_TypeTraitBasicCustomizedType'
//:   o 'bsl::vector'
//:   o 'bsl::basic_string'
//
///Usage
///-----
// This section illustrates intended use of this component.
//
///Example 1: Implicit "Value Type"
/// - - - - - - - - - - - - - - - -
// Suppose you had a type that defines a "value".
//..
//  namespace BloombergLP {
//  namespace mine {
//
//  struct MyValueType {
//      int    d_int;
//      double d_double;
//  };
//
//  }  // close package namespace
//  }  // close enterprise namespace
//..
// Although our definition of 'MyValueType' was rather terse, several methods
// are implicitly defined by the compiler:
//..
//  void f()
//  {
//      using namespace BloombergLP;
//
//      mine::MyValueType a = { 1, 1.0 };  // aggregate braced initialization
//      mine::MyValueType b(a);            // implicit copy constructor
//
//      assert(b.d_int    == a.d_int);
//      assert(b.d_double == a.d_double);
//
//      a.d_int    = 2;
//      a.d_double = 3.14;
//
//      b = a;                             // implicit copy assignment operator
//
//      assert(b.d_int    == a.d_int);
//      assert(b.d_double == a.d_double);
//  }
//..
// Notice that the implicitly defined methods include a copy constructor and a
// copy assignment operator thereby implicitly making 'MyValueType' part of the
// 'bdlat' "value" framework.  As such, it can be manipulated using the methods
// of 'bdlat_ValueTypeFunctions':
//..
//  void myUsageScenario()
//  {
//      using namespace BloombergLP;
//
//      mine::MyValueType x = {  7, 10.0 };
//      mine::MyValueType y = { 99, -1.0 };
//
//      assert(x.d_int    != y.d_int);
//      assert(x.d_double != y.d_double);
//
//      int rc = bdlat_ValueTypeFunctions::assign(&x, y);
//      assert(0 == rc);
//
//      assert(x.d_int    == y.d_int);
//      assert(x.d_double == y.d_double);
//
//      bdlat_ValueTypeFunctions::reset(&y);
//
//      assert(x.d_int    != y.d_int);
//      assert(x.d_double != y.d_double);
//
//      assert(int()    == y.d_int);
//      assert(double() == y.d_double);
//  }
//..
//
///Example 2: Interacting with Other Types
///- - - - - - - - - - - - - - - - - - - -
// Suppose you want to enhance 'mine::MyValueType' to allow its value to be
// assigned from a 'bsl::pair<int, float>' object?  Do do so, create
// 'your::YourValueType' which has an implicit conversion from
// 'bsl::pair<int, float>':
//..
//  namespace BloombergLP {
//  namespace your {
//
//  struct YourValueType {
//
//      int    d_int;
//      double d_double;
//
//      YourValueType()
//      : d_int()
//      , d_double() { }
//
//      YourValueType(const YourValueType& original)
//      : d_int   (original.d_int)
//      , d_double(original.d_double) { }
//
//      YourValueType(int intValue, double doubleValue)
//      : d_int   (   intValue)
//      , d_double(doubleValue) { }
//
//      YourValueType(const bsl::pair<int, double>& value) // IMPLICIT
//      : d_int   (value.first)
//      , d_double(value.second) { }
//
//  };
//
//  }  // close package namespace
//  }  // close enterprise namespace
//..
// Notice that, having defined a constructor, the compiler no longer generates
// the constructors that had been generated implicitly.  Accordingly, we have
// added a default constructor and copy constructor.  Also, since aggregate
// initialization is no longer allowed, we have also added a value constructor
// and slightly modified the syntax of initialization in function 'g()' below:
//..
//  void g()
//  {
//      using namespace BloombergLP;
//
//      your::YourValueType a(1, 1.0);     // value initialization
//      your::YourValueType b(a);          // implicit copy constructor
//
//      assert(b.d_int    == a.d_int);
//      assert(b.d_double == a.d_double);
//
//      a.d_int    = 2;
//      a.d_double = 3.14;
//
//      b = a;                             // implicit copy assignment operator
//
//      assert(b.d_int    == a.d_int);
//      assert(b.d_double == a.d_double);
//
//      bsl::pair<int, double> value(4, 5.0);
//
//      a = value;
//
//      assert(4   == a.d_int);
//      assert(5.0 == a.d_double);
//  }
//..
// Since both copy construction and assignment are defined, 'YourValueType' can
// be handled by the 'bdlat' "value" infrastructure in much the same way as we
// did for 'MyValueType':
//..
//  void yourUsageScenario()
//  {
//      using namespace BloombergLP;
//      int rc;
//
//      your::YourValueType x( 7, 10.0);
//      your::YourValueType y(99, -1.0);
//
//      assert(x.d_int    != y.d_int);
//      assert(x.d_double != y.d_double);
//
//      rc = bdlat_ValueTypeFunctions::assign(&x, y);
//      assert(0 == rc);
//
//      assert(x.d_int    == y.d_int);
//      assert(x.d_double == y.d_double);
//
//      bdlat_ValueTypeFunctions::reset(&y);
//
//      assert(x.d_int    != y.d_int);
//      assert(x.d_double != y.d_double);
//
//      assert(int()   == y.d_int);
//      assert(float() == y.d_double);
//..
// However, since conversion from another type, 'bsl::pair<int, double>', is
// provided, the 'bdlat' "value" infrastructure can also use that type to set
// the value of objects.
//..
//      bsl::pair<int, double> value(4, 5.0);
//
//      rc = bdlat_ValueTypeFunctions::assign(&y, value);
//      assert(0 == rc);
//
//      assert(value.first  == y.d_int);
//      assert(value.second == y.d_double);
//..
// Unsurprisingly, such assignments do not work for arbitrary other types (for
// which conversion is not defined).  What is notable, is that this code does
// compile and fails at run-time.
//..
//      // Assign an incompatible type.
//      rc = bdlat_ValueTypeFunctions::assign(&y, bsl::string("4, 5.0"));
//      assert(0 != rc);
//  }
//..
//
///Installing an Atypical "Value" Type
///- - - - - - - - - - - - - - - - - -
// Suppose someone defines a pernicious "value" type, 'their::TheirValueType',
// having neither copy constructor nor copy assignment operator:
//..
//  namespace BloombergLP {
//  namespace their {
//
//  class TheirValueType {
//
//      // DATA
//      int    d_int;
//      double d_double;
//
//    private:
//      // NOT IMPLEMENTED
//      TheirValueType(const TheirValueType& original);   // = delete
//      TheirValueType& operator=(const TheirValueType&); // = delete
//
//    public:
//      // CREATORS
//      TheirValueType()
//      : d_int()
//      , d_double() { }
//
//      // MANIPULATORS
//      void setValue(const bsl::string& valueString);
//
//      // ACCESSORS
//      int       intValue() const { return d_int;    }
//      double doubleValue() const { return d_double; }
//  };
//
//  // MANIPULATORS
//  void TheirValueType::setValue(const bsl::string& valueString)
//  {
//       bsl::string::size_type pos = valueString.find(',');
//       BSLS_ASSERT(bsl::string::npos != pos);
//
//       d_int    = bsl::atoi(valueString.c_str());
//       d_double = bsl::atof(valueString.c_str() + pos + 1);
//  }
//
//  }  // close package namespace
//  }  // close enterprise namespace
//..
// Such a type can be used after a fashion (objects created, states changed,
// state changes observed), albeit using syntax that is significantly different
// than we used for 'MyValueType' and 'YourValueType':
//..
//  void h()
//  {
//      using namespace BloombergLP;
//
//      their::TheirValueType a;               // default constructor
//
//      assert(0   == a.   intValue());
//      assert(0.0 == a.doubleValue());
//
//  //  their::TheirValueType b(a);       // Error, no copy constructor
//
//      their::TheirValueType c;
//  //  c = a;                            // Error, no copy assignment operator
//
//      a.setValue("2, 3.14");
//
//      assert(2    == a.   intValue());
//      assert(3.14 == a.doubleValue());
//  }
//..
// Since 'TheirValueType' lacks both copy construction and assignment, that
// type is not implicitly supported by the 'bdlat' "value" infrastructure.
//
// However, the 'TheirValueType' can be made compatible with that
// infrastructure if "they" define the required overloads of
// 'bdlat_valueTypeAssign' and 'bdlat_valueTypeReset' in 'their' namespace:
//..
//  namespace BloombergLP {
//  namespace their {
//
//  int bdlat_valueTypeAssign(TheirValueType        *lhs,
//                            const TheirValueType&  rhs)
//  {
//      BSLS_ASSERT(lhs);
//
//      bsl::ostringstream oss;
//      oss << rhs.intValue() << ", " << rhs.doubleValue();
//
//      lhs->setValue(oss.str());
//      return 0;
//  }
//
//  int bdlat_valueTypeAssign(TheirValueType     *lhs,
//                            const bsl::string&  rhs)
//  {
//      BSLS_ASSERT(lhs);
//
//      lhs->setValue(rhs);
//      return 0;
//  }
//
//  // Overload for any other 'RHS_TYPE' to return an error.
//  template <class RHS_TYPE>
//  int bdlat_valueTypeAssign(TheirValueType  *lhs,
//                            const RHS_TYPE&  rhs)
//  {
//      BSLS_ASSERT(lhs);
//      (void)rhs;
//
//      return -999;  // Pick a distinctive non-negative value.
//  }
//  void bdlat_valueTypeReset(TheirValueType *object)
//  {
//      BSLS_ASSERT(object);
//
//      bsl::ostringstream oss;
//      oss << int() << ", " << double();
//
//      object->setValue(oss.str());
//  }
//
//  }  // close package namespace
//  }  // close enterprise namespace
//..
// Notice that three overloads of 'bdlat_valueTypeAssign' are defined above:
//
//: o The first, the overload that allows 'TheirValueType' to be "assigned" to
//:   itself is required by the 'bdlat' "value" infrastructure.
//:
//: o The second, the overload that allows "assignment" from a 'bsl::string' is
//:   not technically required by the infrastructure, but is a practical
//:   requirement because 'bsl::string' is the only way 'TheirValueType' can be
//:   changed from its default value.
//:
//: o Finally, we provide an overload templated on an arbitrary 'RHS_TYPE' so
//:   that, if any other types are passed, the code will compile (as required)
//:   but also unconditionally fail (as required).
//
// With these points of customization in place, 'TheirValueType' can now be
// manipulated by the 'bdlat' "value" infrastructure in much the same manner as
// was done for 'MyValueType' and 'YourValueType':
//..
//  void theirUsageScenario()
//  {
//      using namespace BloombergLP;
//
//      their::TheirValueType x;
//      their::TheirValueType y;
//
//      int rc;
//
//      rc = bdlat_ValueTypeFunctions::assign(&x, bsl::string(" 7, 10.0"));
//      assert(0 == rc);
//
//      rc = bdlat_ValueTypeFunctions::assign(&y, bsl::string("99, -1.0"));
//      assert(0 == rc);
//
//      assert(x.intValue()    != y.intValue());
//      assert(x.doubleValue() != y.doubleValue());
//
//      rc = bdlat_ValueTypeFunctions::assign(&x, y);
//      assert(0 == rc);
//
//      assert(x.intValue()    == y.intValue());
//      assert(x.doubleValue() == y.doubleValue());
//
//      bdlat_ValueTypeFunctions::reset(&y);
//
//      assert(int()   == y.intValue());
//      assert(float() == y.doubleValue());
//
//      // Assign an incompatible type.
//
//      bsl::pair<int, double> value(4, 5.0);
//      rc = bdlat_ValueTypeFunctions::assign(&y, value);
//      assert(   0 != rc);
//      assert(-999 == rc);
//  }
//..

#include <bdlscm_version.h>

#include <bdlat_bdeatoverrides.h>
#include <bdlat_enumfunctions.h>
#include <bdlat_typecategory.h>
#include <bdlat_typetraits.h>

#include <bdlb_nullablevalue.h>

#include <bslalg_hastrait.h>

#include <bslmf_conditional.h>
#include <bslmf_isconvertible.h>

#include <bsls_platform.h>

#include <bsl_string.h>
#include <bsl_vector.h>

#ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
#include <bslmf_if.h>
#endif  // BDE_DONT_ALLOW_TRANSITIVE_INCLUDES

namespace BloombergLP {

                      // ==================================
                      // namespace bdlat_ValueTypeFunctions
                      // ==================================

namespace bdlat_ValueTypeFunctions {
    // The functions provided in this 'namespace' may be applied to value
    // types.  See the component-level documentation for what is meant by
    // "value type".

    // MANIPULATORS
    template <class LHS_TYPE, class RHS_TYPE>
    int assign(LHS_TYPE *lhs, const RHS_TYPE& rhs);
        // Assign the value of the specified 'rhs' to the object specified its
        // address 'lhs'.  Return 0 if successful, and a non-zero value
        // otherwise.

    template <class TYPE>
    void reset(TYPE *object);
        // Reset the value of the specified 'object' to its default value.

}  // close namespace bdlat_ValueTypeFunctions

                            // ====================
                            // default declarations
                            // ====================

namespace bdlat_ValueTypeFunctions {
    // This namespace declaration adds the default implementations of the
    // "value type" customization-point functions to
    // 'bdlat_ValueTypeFunctions'.  These default implementations are provided
    // for a variety of types.

    // MANIPULATORS
    template <class LHS_TYPE, class RHS_TYPE>
    int bdlat_valueTypeAssign(LHS_TYPE *lhs, const RHS_TYPE& rhs);

    template <class TYPE>
    void bdlat_valueTypeReset(TYPE *object);

}  // close namespace bdlat_ValueTypeFunctions

                    // ===================================
                    // struct bdlat_ValueTypeFunctions_Imp
                    // ===================================

struct bdlat_ValueTypeFunctions_Imp {
    // This 'struct' contains functions used by the implementation of this
    // component.

    // TYPES
    struct IsConvertible    { };
    struct IsNotConvertible { };
    struct UseResetMethod   { };
    struct UseDefaultCtor   { };

    // CLASS METHODS
    template <class LHS_TYPE>
    static int assign(LHS_TYPE                        *lhs,
                      bdlat_TypeCategory::Enumeration  ,
                      const char&                      rhs,
                      bdlat_TypeCategory::Simple       );

    template <class LHS_TYPE>
    static int assign(LHS_TYPE                        *lhs,
                      bdlat_TypeCategory::Enumeration  ,
                      const short&                     rhs,
                      bdlat_TypeCategory::Simple       );

    template <class LHS_TYPE>
    static int assign(LHS_TYPE                        *lhs,
                      bdlat_TypeCategory::Enumeration  ,
                      const int&                       rhs,
                      bdlat_TypeCategory::Simple       );

    template <class LHS_TYPE>
    static int assign(LHS_TYPE                        *lhs,
                      bdlat_TypeCategory::Enumeration  ,
                      const bsl::string&               rhs,
                      bdlat_TypeCategory::Simple       );

    template <class RHS_TYPE>
    static int assign(char                            *lhs,
                      bdlat_TypeCategory::Simple       ,
                      const RHS_TYPE&                  rhs,
                      bdlat_TypeCategory::Enumeration  );

    template <class RHS_TYPE>
    static int assign(short                           *lhs,
                      bdlat_TypeCategory::Simple       ,
                      const RHS_TYPE&                  rhs,
                      bdlat_TypeCategory::Enumeration  );

    template <class RHS_TYPE>
    static int assign(int                             *lhs,
                      bdlat_TypeCategory::Simple       ,
                      const RHS_TYPE&                  rhs,
                      bdlat_TypeCategory::Enumeration  );

    template <class RHS_TYPE>
    static int assign(bsl::string                     *lhs,
                      bdlat_TypeCategory::Simple       ,
                      const RHS_TYPE&                  rhs,
                      bdlat_TypeCategory::Enumeration  );

    template <class LHS_TYPE, class RHS_TYPE>
    static int assign(LHS_TYPE                   *lhs,
                      bdlat_TypeCategory::Simple  ,
                      const RHS_TYPE&             rhs,
                      bdlat_TypeCategory::Simple  );

    template <class LHS_TYPE,
              class LHS_CATEGORY,
              class RHS_TYPE,
              class RHS_CATEGORY>
    static int assign(LHS_TYPE        *lhs,
                      LHS_CATEGORY,
                      const RHS_TYPE&  rhs,
                      RHS_CATEGORY);

    template <class LHS_TYPE, class RHS_TYPE>
    static int assignSimpleTypes(LHS_TYPE        *lhs,
                                 const RHS_TYPE&  rhs,
                                 IsConvertible    );

    template <class LHS_TYPE, class RHS_TYPE>
    static int assignSimpleTypes(LHS_TYPE         *lhs,
                                 const RHS_TYPE&   rhs,
                                 IsNotConvertible  );

    template <class TYPE>
    static void reset(TYPE *object);

    template <class TYPE>
    static void reset(bdlb::NullableValue<TYPE> *object);

    template <class TYPE, class ALLOC>
    static void reset(bsl::vector<TYPE, ALLOC> *object);

    template <class CHAR_T, class CHAR_TRAITS, class ALLOC>
    static void reset(bsl::basic_string<CHAR_T, CHAR_TRAITS, ALLOC> *object);

    template <class TYPE>
    static void reset(TYPE *object, UseResetMethod);

    template <class TYPE>
    static void reset(TYPE *object, UseDefaultCtor);

};

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

                      // ----------------------------------
                      // namespace bdlat_ValueTypeFunctions
                      // ----------------------------------

// MANIPULATORS
template <class LHS_TYPE, class RHS_TYPE>
inline
int bdlat_ValueTypeFunctions::assign(LHS_TYPE *lhs, const RHS_TYPE& rhs)
{
    return bdlat_valueTypeAssign(lhs, rhs);
}

template <class TYPE>
inline
void bdlat_ValueTypeFunctions::reset(TYPE *object)
{
    return bdlat_valueTypeReset(object);
}

                            // -------------------
                            // default definitions
                            // -------------------

// MANIPULATORS
template <class LHS_TYPE, class RHS_TYPE>
inline
int bdlat_ValueTypeFunctions::bdlat_valueTypeAssign(LHS_TYPE        *lhs,
                                                    const RHS_TYPE&  rhs)
{
    typedef typename bdlat_TypeCategory::Select<LHS_TYPE>::Type LhsCategory;
    typedef typename bdlat_TypeCategory::Select<RHS_TYPE>::Type RhsCategory;

    return bdlat_ValueTypeFunctions_Imp::assign(lhs,
                                                LhsCategory(),
                                                rhs,
                                                RhsCategory());
}

template <class TYPE>
inline
void bdlat_ValueTypeFunctions::bdlat_valueTypeReset(TYPE *object)
{
    bdlat_ValueTypeFunctions_Imp::reset(object);
}

                    // -----------------------------------
                    // struct bdlat_ValueTypeFunctions_Imp
                    // -----------------------------------

// CLASS METHODS
template <class LHS_TYPE>
int bdlat_ValueTypeFunctions_Imp::assign(LHS_TYPE                        *lhs,
                                         bdlat_TypeCategory::Enumeration  ,
                                         const char&                      rhs,
                                         bdlat_TypeCategory::Simple       )
{
    return bdlat_EnumFunctions::fromInt(lhs, rhs);
}

template <class LHS_TYPE>
int bdlat_ValueTypeFunctions_Imp::assign(LHS_TYPE                        *lhs,
                                         bdlat_TypeCategory::Enumeration  ,
                                         const short&                     rhs,
                                         bdlat_TypeCategory::Simple       )
{
    return bdlat_EnumFunctions::fromInt(lhs, rhs);
}

template <class LHS_TYPE>
int bdlat_ValueTypeFunctions_Imp::assign(LHS_TYPE                        *lhs,
                                         bdlat_TypeCategory::Enumeration  ,
                                         const int&                       rhs,
                                         bdlat_TypeCategory::Simple       )
{
    return bdlat_EnumFunctions::fromInt(lhs, rhs);
}

template <class LHS_TYPE>
int bdlat_ValueTypeFunctions_Imp::assign(LHS_TYPE                        *lhs,
                                         bdlat_TypeCategory::Enumeration  ,
                                         const bsl::string&               rhs,
                                         bdlat_TypeCategory::Simple       )
{
    return bdlat_EnumFunctions::fromString(lhs, rhs.data(), (int)rhs.length());
}

template <class RHS_TYPE>
int bdlat_ValueTypeFunctions_Imp::assign(char                            *lhs,
                                         bdlat_TypeCategory::Simple       ,
                                         const RHS_TYPE&                  rhs,
                                         bdlat_TypeCategory::Enumeration  )
{
    enum { k_SUCCESS = 0, k_FAILURE = -1 };

    const int MIN_CHAR = -128;
    const int MAX_CHAR =  127;

    int proxy;

    bdlat_EnumFunctions::toInt(&proxy, rhs);

    if (proxy < MIN_CHAR || proxy > MAX_CHAR) {
        return k_FAILURE;                                             // RETURN
    }

    *lhs = static_cast<char>(proxy);

    return k_SUCCESS;
}

template <class RHS_TYPE>
int bdlat_ValueTypeFunctions_Imp::assign(short                           *lhs,
                                         bdlat_TypeCategory::Simple       ,
                                         const RHS_TYPE&                  rhs,
                                         bdlat_TypeCategory::Enumeration  )
{
    enum { k_SUCCESS = 0, k_FAILURE = -1 };

    const int MIN_SHORT = -32768;
    const int MAX_SHORT =  32767;

    int proxy;

    bdlat_EnumFunctions::toInt(&proxy, rhs);

    if (proxy < MIN_SHORT || proxy > MAX_SHORT) {
        return k_FAILURE;                                             // RETURN
    }

    *lhs = static_cast<short>(proxy);

    return k_SUCCESS;
}

template <class RHS_TYPE>
int bdlat_ValueTypeFunctions_Imp::assign(int                             *lhs,
                                         bdlat_TypeCategory::Simple       ,
                                         const RHS_TYPE&                  rhs,
                                         bdlat_TypeCategory::Enumeration  )
{
    enum { k_SUCCESS = 0 };

    bdlat_EnumFunctions::toInt(lhs, rhs);

    return k_SUCCESS;
}

template <class RHS_TYPE>
int bdlat_ValueTypeFunctions_Imp::assign(bsl::string                     *lhs,
                                         bdlat_TypeCategory::Simple       ,
                                         const RHS_TYPE&                  rhs,
                                         bdlat_TypeCategory::Enumeration  )
{
    enum { k_SUCCESS = 0 };

    bdlat_EnumFunctions::toString(lhs, rhs);

    return k_SUCCESS;
}

template <class LHS_TYPE, class RHS_TYPE>
int bdlat_ValueTypeFunctions_Imp::assign(LHS_TYPE                   *lhs,
                                         bdlat_TypeCategory::Simple  ,
                                         const RHS_TYPE&             rhs,
                                         bdlat_TypeCategory::Simple  )
{
    enum {
        IS_CONVERTIBLE = bslmf::IsConvertible<RHS_TYPE, LHS_TYPE>::VALUE
    };

    typedef typename bsl::conditional<IS_CONVERTIBLE,
                                      IsConvertible,
                                      IsNotConvertible>::type Selector;

    return assignSimpleTypes(lhs, rhs, Selector());
}

template <class LHS_TYPE,
          class LHS_CATEGORY,
          class RHS_TYPE,
          class RHS_CATEGORY>
int bdlat_ValueTypeFunctions_Imp::assign(LHS_TYPE        *,
                                         LHS_CATEGORY     ,
                                         const RHS_TYPE&  ,
                                         RHS_CATEGORY     )
{
    enum { k_FAILURE = -1 };

    return k_FAILURE;
}

template <class LHS_TYPE, class RHS_TYPE>
inline
int bdlat_ValueTypeFunctions_Imp::assignSimpleTypes(LHS_TYPE        *lhs,
                                                    const RHS_TYPE&  rhs,
                                                    IsConvertible    )
{
    enum { k_SUCCESS = 0 };

    *lhs = static_cast<LHS_TYPE>(rhs);

    return k_SUCCESS;
}

template <class LHS_TYPE, class RHS_TYPE>
inline
int bdlat_ValueTypeFunctions_Imp::assignSimpleTypes(LHS_TYPE         *,
                                                    const RHS_TYPE&   ,
                                                    IsNotConvertible  )
{
    enum { k_FAILURE = -1 };

    return k_FAILURE;
}

template <class TYPE>
inline
void bdlat_ValueTypeFunctions_Imp::reset(TYPE *object)
{
    enum {
        HAS_TRAIT = bslalg::HasTrait<TYPE, bdlat_TypeTraitBasicChoice>::VALUE
                 || bslalg::HasTrait<TYPE, bdlat_TypeTraitBasicSequence>::VALUE
                 || bslalg::HasTrait<TYPE,
                                    bdlat_TypeTraitBasicCustomizedType>::VALUE
    };

    typedef typename bsl::conditional<
                  HAS_TRAIT,
                  bdlat_ValueTypeFunctions_Imp::UseResetMethod,
                  bdlat_ValueTypeFunctions_Imp::UseDefaultCtor>::type Selector;

    bdlat_ValueTypeFunctions_Imp::reset(object, Selector());
}

template <class TYPE>
inline
void bdlat_ValueTypeFunctions_Imp::reset(bdlb::NullableValue<TYPE> *object)
{
    object->reset();
}

template <class TYPE, class ALLOC>
inline
void bdlat_ValueTypeFunctions_Imp::reset(bsl::vector<TYPE, ALLOC> *object)
{
    object->clear();
}

template <class CHAR_T, class CHAR_TRAITS, class ALLOC>
inline
void bdlat_ValueTypeFunctions_Imp::reset(
                         bsl::basic_string<CHAR_T, CHAR_TRAITS, ALLOC> *object)
{
    object->erase();
}

template <class TYPE>
inline
void bdlat_ValueTypeFunctions_Imp::reset(TYPE *object, UseResetMethod)
{
    object->reset();
}

template <class TYPE>
inline
void bdlat_ValueTypeFunctions_Imp::reset(TYPE *object, UseDefaultCtor)
{
    *object = TYPE();
}

}  // 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 ----------------------------------