// bslmf_forwardingtype.h                                             -*-C++-*-
#ifndef INCLUDED_BSLMF_FORWARDINGTYPE
#define INCLUDED_BSLMF_FORWARDINGTYPE

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

//@PURPOSE: Provide a meta-function for determining an optimal forwarding type.
//
//@CLASSES:
//  bslmf::ForwardingType: meta-function to determine optimal forwarding type
//  bslmf::ForwardingTypeUtil: Namespace for forwarding functions
//
//@SEE_ALSO: bslmf_removecvq
//
//@DESCRIPTION: This component, while not deprecated, is largely **superseded**
// by the simpler 'bslmf_forwardingreftype'.  Although there may be use cases
// for which 'bslmf_forwardingtype' is to be prefered, new users are encouraged
// to consider 'bslmf_forwardingreftype' and understand the differences between
// the two components (see {Comparison to 'bslmf_forwardingreftype'}).
//
// This component provides a meta function, 'bslmf::ForwardingType',
// determining the most efficient forwarding type for a given template type
// 't_TYPE'.  The forwarding type is used to pass an argument from the client
// of a component through a chain of nested function calls to the ultimate
// consumer of the argument.  This component also provides a utility class
// template, 'bslmf::ForwardingTypeUtil', supplying functions to most
// efficiently forward an argument to another function.
//
// For instance, basic types (e.g., fundamental types, pointer types, function
// references and pointers) can efficiently be passed by value down a chain of
// nested function calls.  However a large object or one with a non-trivial
// copy constructor would be better passed by const reference, even if the
// ultimate consumer takes that argument by value.
//
// Another form of optimization is the early decay of arrays to pointers,
// preventing a proliferation of different template instantiations for every
// array size being used.  Although the outermost function may still be
// instantiated on the full array type, intermediate functions are all
// instantiated on the same pointer type, regardless of array size.  This
// decay also applies to reference-to-array types.  The user can recover the
// original array type when forwarding to the final consumer by using
// 'bslmf::ForwardingTypeUtil<T>::forwardToTarget()' (see below).
//
// An argument 'v' of type 'T' can be passed as type 'ForwardingType<T>::Type'
// down an arbitrarily-long chain of function calls without ever calling
// 'std::forward'.  However, in order to avoid an extra copy as well as to
// select the correct overload and instantiation of the eventual target
// function, it should be converted back to a type that more closely resembles
// the original 'T' by calling 'ForwardingTypeUtil<T>::forwardToTarget(v)'.
//
// This component is intended to be used when performance is of highest concern
// or when creating function wrappers that are intended to minimize
// perturbations on the interface of the functions that they wrap.
//
// Note that previous versions of this component forwarded const references to
// basic types by value instead of by const reference.  This transformation was
// an attempt to avoid an extra dereference operation, but in real use cases
// the extra dereference happened anyway, on the call to the outermost
// forwarding function.  Moreover, such a transformation is subtly broken
// because, in the rare case where the target function cares about the address
// of the reference (e.g., if it compares it to some known address), it would
// wind up with the address of a temporary copy, rather than the address of the
// original argument.  Thus, the current component forwards references as
// references in all cases, including for basic types, except in the case of
// arrays and functions (that decay to pointers).
//
///Comparison to 'bslmf_forwardingreftype'
///---------------------------------------
// The components 'bslmf_forwardingtype' and 'bslmf_forwardingreftype' serve
// the same purpose but have small behavioral differences.  In general, we
// recommend 'bslmf_forwardingreftype' (the new component) in most contexts.
//
// Most notably, 'bslmf::ForwardingType' (the older class) forwards fundamental
// and pointer types by value, where as 'bslmf::ForwardingRefType' will forward
// fundamental and pointer types by const-reference.  For example,
// 'bslmf::ForwardingType<int>::Type' is 'int' where as
// 'bslmf::ForwardingRefType<int>::Type' is 'const int&'.  This applies to
// fundamental types, pointer types (including member-pointer types), and enum
// types (which we'll collectively call "basic types").  Forwarding these basic
// types by value was a performance optimization (and in some rare
// circumstances was hack needed by older compilers), which predated the
// standardization of many of the places where 'bslmf::ForwardingType' was used
// (function and bind components in particular).  The optimzation (potentially)
// being that passing an 'int' by value is more likely to be done through a
// register, where as passing by reference is more likely to require
// de-referencing memory.  Forwarding the types by const-reference, as the
// newer 'bslmf::ForwardingRefType' does', is generally simpler and more in
// line with the modern C++ standard.  Using 'bslmf::ForwardingRefType' avoids
// some awkward edge cases at the expense of a possible optimization in
// parameter passing.
//
///Usage
///-----
// In this section we show intended use of this component.
//
///Example 1: Direct Look at Metafunction Results
/// - - - - - - - - - - - - - - - - - - - - - - -
// In this example, we invoke 'ForwardingType' on a variety of types and look
// at the resulting 'Type' member:
//..
//  struct MyType {};
//  typedef MyType& MyTypeRef;
//
//  void main()
//      // Usage example.
//  {
//      typedef int                     T1;
//      typedef int&                    T2;
//      typedef const volatile double&  T3;
//      typedef const double &          T4;
//      typedef const float * &         T5;
//      typedef const float * const &   T6;
//      typedef MyType                  T7;
//      typedef const MyType&           T8;
//      typedef MyType&                 T9;
//      typedef MyType                 *T10;
//      typedef int                     T11[];
//      typedef int                     T12[3];
//
//      typedef int                     EXP1;
//      typedef int&                    EXP2;
//      typedef const volatile double&  EXP3;
//      typedef const double &          EXP4;
//      typedef const float * &         EXP5;
//      typedef const float * const &   EXP6;
//      typedef const MyType&           EXP7;
//      typedef const MyType&           EXP8;
//      typedef MyType&                 EXP9;
//      typedef MyType                 *EXP10;
//      typedef int                    *EXP11;
//      typedef int                    *EXP12;
//
//      assert((bsl::is_same<bslmf::ForwardingType<T1>::Type, EXP1>::value));
//      assert((bsl::is_same<bslmf::ForwardingType<T2>::Type, EXP2>::value));
//      assert((bsl::is_same<bslmf::ForwardingType<T3>::Type, EXP3>::value));
//      assert((bsl::is_same<bslmf::ForwardingType<T4>::Type, EXP4>::value));
//      assert((bsl::is_same<bslmf::ForwardingType<T5>::Type, EXP5>::value));
//      assert((bsl::is_same<bslmf::ForwardingType<T6>::Type, EXP6>::value));
//      assert((bsl::is_same<bslmf::ForwardingType<T7>::Type, EXP7>::value));
//      assert((bsl::is_same<bslmf::ForwardingType<T8>::Type, EXP8>::value));
//      assert((bsl::is_same<bslmf::ForwardingType<T9>::Type, EXP9>::value));
//      assert((bsl::is_same<bslmf::ForwardingType<T10>::Type, EXP10>::value));
//      assert((bsl::is_same<bslmf::ForwardingType<T11>::Type, EXP11>::value));
//      assert((bsl::is_same<bslmf::ForwardingType<T12>::Type, EXP12>::value));
//  }
//..
//
///Example 2: A Logging Invocation Wrapper
///- - - - - - - - - - - - - - - - - - - -
// This example illustrates the use of 'ForwardingType' to efficiently
// implement a wrapper class that holds a function pointer and logs
// information about each call to the pointed-to-function through the wrapper.
// Suppose the pointed-to-function takes three arguments whose types are
// specified via template arguments, where the first argument is required to
// be convertible to 'int'.
//
// First we create a wrapper class that holds a function pointer of the
// desired type:
//..
//  // Primary template is never defined.
//  template <class PROTOTYPE>
//  class LoggingWrapper;
//
//  template <class RET, class ARG1, class ARG2, class ARG3>
//  class LoggingWrapper<RET(ARG1, ARG2, ARG3)> {
//      // Specialization of wrapper for specified function prototype.
//
//      RET (*d_function_p)(ARG1, ARG2, ARG3);
//
//    public:
//      explicit LoggingWrapper(RET (*function_p)(ARG1, ARG2, ARG3))
//          // Create a 'LoggingWrapper' object for the specified 'function_p'
//          // function.
//        : d_function_p(function_p) { }
//..
// Then, we declare an overload of the function-call operator that actually
// invokes the wrapped function.  In order to avoid excessive copies of
// pass-by-value arguments, we use 'ForwardingType' to declare a more efficient
// intermediate argument type to forward to the wrapped function pointer:
//..
//      RET operator()(typename bslmf::ForwardingType<ARG1>::Type a1,
//                     typename bslmf::ForwardingType<ARG2>::Type a2,
//                     typename bslmf::ForwardingType<ARG3>::Type a3) const;
//          // Invoke the stored function pointer with the specified 'a1',
//          // 'a2', and 'a3' arguments, logging the invocation and returning
//          // the result of the function pointer invocation.
//  };
//..
// Next, we define logging functions that simply count the number of
// invocations and number of returns from invocations (e.g., to count how may
// invocations completed without exiting via exceptions):
//..
//  int invocations = 0, returns = 0;
//  void logInvocation(int /* ignored */) { ++invocations; }
//      // Log an invocation of the wrapped function.
//  void logReturn(int /* ignored */) { ++returns; }
//      // Log a return from the wrapped function.
//..
// Now, we implement 'operator()' to call the logging functions, either side of
// calling the logged function through the wrapped pointer.  To reconstitute
// the arguments to the function as close as possible to the types they were
// passed in as, we call the 'forwardToTarget' member of 'ForwardingTypeUtil':
//..
//  template <class RET, class ARG1, class ARG2, class ARG3>
//  RET LoggingWrapper<RET(ARG1, ARG2, ARG3)>::operator()(
//                       typename bslmf::ForwardingType<ARG1>::Type a1,
//                       typename bslmf::ForwardingType<ARG2>::Type a2,
//                       typename bslmf::ForwardingType<ARG3>::Type a3) const {
//      logInvocation(a1);
//      RET r = d_function_p(
//          bslmf::ForwardingTypeUtil<ARG1>::forwardToTarget(a1),
//          bslmf::ForwardingTypeUtil<ARG2>::forwardToTarget(a2),
//          bslmf::ForwardingTypeUtil<ARG3>::forwardToTarget(a3));
//      logReturn(a1);
//      return r;
//  }
//..
// Then, in order to see this wrapper in action, we must define a function we
// wish to wrap.  This function will take an argument of type 'ArgType' that
// holds an integer 'value' and keeps track of whether it has been directly
// constructed or copied from anther 'ArgType' object.  If it has been copied,
// it keeps track of how many "generations" of copy were made:
//..
//  class ArgType {
//      int d_value;
//      int d_copies;
//    public:
//      explicit ArgType(int v = 0) : d_value(v), d_copies(0) { }
//          // Create an 'ArgType' object.  Optionally specify 'v' as the
//          // initial value of this 'ArgType' object, otherwise this object
//          // will hold the value 0.
//
//      ArgType(const ArgType& original)
//          // Create an 'ArgType' object that is a copy of the specified
//          // 'original'.
//      : d_value(original.d_value)
//      , d_copies(original.d_copies + 1)
//      { }
//
//      int copies() const { return d_copies; }
//          // Return the number of copies that this object is from the
//          // original.
//
//      int value() const { return d_value; }
//          // Return the value of this object.
//  };
//
//  int myFunc(const short& i, ArgType& x, ArgType y)
//      // Assign the specified 'x' the value of the specified 'y' and return
//      // the 'value()' of 'x'.  Verify that the specified 'i' matches
//      // 'y.copies()'.  'x' is passed by reference in order to demonstrate
//      // forwarding of reference arguments.
//  {
//      assert(i == y.copies());
//      x = y;
//      return x.value();
//  }
//..
// Finally, we create a instance of 'LoggingWrapper' to wrap 'myFunc', and we
// invoke it.  Note that 'y' is copied into the second argument of 'operator()'
// and is copied again when 'myFunc' is invoked.  However, it is *not* copied
// when 'operator()' calls 'invoke()' because the 'ForwardType' of 'ArgType' is
// 'const ArgType&', which does not create another copy.  In C++11, if
// 'ArgType' had a move constructor, then the number of copies would be only 1,
// since the final forwarding would be a move instead of a copy.
//..
//  void usageExample2()
//      // Usage Example
//  {
//      ArgType x(0);
//      ArgType y(99);
//
//      LoggingWrapper<int(const short&, ArgType&, ArgType)> lw(myFunc);
//      assert(0 == invocations && 0 == returns);
//      lw(1, x, y);  // Expect exactly one copy of 'y'
//      assert(1 == invocations && 1 == returns);
//      assert(99 == x.value());
//  }
//..

#include <bslscm_version.h>

#include <bslmf_isarray.h>
#include <bslmf_isenum.h>
#include <bslmf_isfunction.h>
#include <bslmf_isfundamental.h>
#include <bslmf_ispointer.h>
#include <bslmf_ismemberpointer.h>
#include <bslmf_isreference.h>
#include <bslmf_isrvaluereference.h>
#include <bslmf_movableref.h>
#include <bslmf_removecv.h>
#include <bslmf_removereference.h>

#include <bsls_compilerfeatures.h>
#include <bsls_platform.h>

#include <stddef.h>

#if defined(BSLS_PLATFORM_CMP_IBM) &&                                         \
    ((BSLS_PLATFORM_CMP_VERSION  < 0x0c10) ||                                 \
     (BSLS_PLATFORM_CMP_VERSION == 0x0c10  && __xlC_ver__ < 0x00000013))
# define BSLMF_FORWARDINGTYPE_NO_INLINE
// THe IBM xlC compiler trips an ICE or infinite compile loop when certain
// functions are inlined for optimized builds.  This is resolved by the August
// 2017 PTF release, 12.1.0.19.
#endif

namespace BloombergLP {


namespace bslmf {

// FORWARD DECLARATIONS
template <class t_TYPE>
class ForwardingTypeUtil;

template <class t_TYPE, int k_CATEGORY>
struct ForwardingType_Imp;

                        // =============================
                        // class ForwardingType_Category
                        // =============================

struct ForwardingType_Category {
    // This component-private struct provides a namespace for thpe type
    // dispatch category enumeration values.

    // CONSTANTS
    enum {
        e_LVALUE_REF,  // Lvalue reference
        e_MOVABLE_REF, // Movable (rvalue) reference
        e_FUNCTION,    // Function or pointer to function
        e_ARRAY,       // Array
        e_BASIC,       // Built-in, pointer, or enum type
        e_CLASS        // Class, struct or union
    };
};

                        // =============================
                        // class ForwardingType_Dispatch
                        // =============================

template <class t_TYPE>
class ForwardingType_Dispatch {
    // This component-private class template is a metafunction whose 'value'
    // member is the forwarding category for the specified 't_TYPE'.

    // PRIVATE TYPES
    typedef ForwardingType_Category Cat;  // Abbreviation

  public:
    enum {
        value = (MovableRefUtil::IsLvalueReference<t_TYPE>::value
                     ? Cat::e_LVALUE_REF
                 : MovableRefUtil::IsMovableReference<t_TYPE>::value
                     ? Cat::e_MOVABLE_REF
                 : bsl::is_function<t_TYPE>::value       ? Cat::e_FUNCTION
                 : bsl::is_array<t_TYPE>::value          ? Cat::e_ARRAY
                 : bsl::is_fundamental<t_TYPE>::value    ? Cat::e_BASIC
                 : bsl::is_pointer<t_TYPE>::value        ? Cat::e_BASIC
                 : bsl::is_member_pointer<t_TYPE>::value ? Cat::e_BASIC
                 : bsl::is_enum<t_TYPE>::value           ? Cat::e_BASIC
                                                         : Cat::e_CLASS)
    };
};

                        // ====================
                        // class ForwardingType
                        // ====================

template <class t_TYPE>
class ForwardingType
: private ForwardingType_Imp<t_TYPE, ForwardingType_Dispatch<t_TYPE>::value> {
    // This template metafunction has a member 'Type' computed such that, for a
    // specified 't_TYPE' parameter, a function with argument of 't_TYPE' can
    // be called efficiently from another function (e.g., a wrapper) by
    // declaring the corresponding parameter of the other wrapper as 'typename
    // ForwardingType<t_TYPE>::Type'.  The 'Type' member is computed to
    // minimize the number of expensive copies while forwarding the arguments
    // as faithfully as possible.

    // PRIVATE TYPES
    typedef ForwardingType_Imp<t_TYPE, ForwardingType_Dispatch<t_TYPE>::value>
        Imp;

  public:
    // TYPES
    typedef typename Imp::Type Type;
        // The type that should be used to forward 't_TYPE' through a chain of
        // function calls.

    typedef typename Imp::TargetType TargetType;
        // The closest type used to "reconstitute" 't_TYPE' from
        // 'ForwardingType<t_TYPE>::Type'.  This type may differ from 't_TYPE'
        // through the addition of a reference.
};

                        // ========================
                        // class ForwardingTypeUtil
                        // ========================

template <class t_TYPE>
class ForwardingTypeUtil
: private ForwardingType_Imp<t_TYPE, ForwardingType_Dispatch<t_TYPE>::value> {
    // Provide a namespace for the 'forwardToTarget' function.

    // PRIVATE TYPES
    typedef ForwardingType_Imp<t_TYPE, ForwardingType_Dispatch<t_TYPE>::value>
        Imp;

  public:
    // TYPES
    typedef typename Imp::TargetType TargetType;
        // The closest type used to "reconstitute" 't_TYPE' from
        // 'ForwardingType<t_TYPE>::Type'.  This type may differ from 't_TYPE'
        // through the addition of a reference.

    // CLASS METHODS static TargetType forwardToTarget(typename
    // ForwardingType<t_TYPE>::Type v);
    using Imp::forwardToTarget;
        // Return (for the specified 'v' parameter) 'std::forward<t_TYPE>(v)',
        // where 'v' is assumed to originally have been an argument of 't_TYPE'
        // after forwarding through an intermediate call chain.  Specifically,
        // if 't_TYPE' is an rvalue type, return an rvalue reference to 'v',
        // otherwise return 'v' unchanged, thus converting an rvalue copy into
        // an rvalue move when possible.  For compilers that do not support
        // rvalue references, return 'v' unchanged.  This function is intended
        // to be called to forward an argument to the final target function of
        // a forwarding call chain.  Note that this function is not intended
        // for use with 't_TYPE' parameters of 'volatile'-qualified rvalue
        // type, which are effectively unheard of in real code and have strange
        // and hard-to-understand rules.
};

                        // =========================
                        // class ConstForwardingType
                        // =========================

#ifndef BDE_OMIT_DEPRECATED

template <class t_TYPE>
struct ConstForwardingType : public ForwardingType<t_TYPE> {
    //!DEPRECATED!: Use 'ForwardingType' instead.
};

#endif // BDE_OMIT_DEPRECATED

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

// BDE_VERIFY pragma: push  // Relax some bde_verify rules in the imp section
// BDE_VERIFY pragma: -CD01 // Member function defined in class definition

                        // ========================
                        // class ForwardingType_Imp
                        // ========================

// PRIMARY TEMPLATE HAS NO DEFINITION

// PARTIAL SPECIALIZATIONS
template <class t_TYPE>
struct ForwardingType_Imp<t_TYPE, ForwardingType_Category::e_LVALUE_REF> {
    // lvalue reference is forwarded unmodified.

    // TYPES
    typedef t_TYPE             Type;
    typedef t_TYPE             TargetType;

    // CLASS METHODS
    static TargetType forwardToTarget(Type v)
        // Return the specified 'v' argument.
    {
        return v;
    }
};

template <class t_TYPE>
struct ForwardingType_Imp<t_TYPE, ForwardingType_Category::e_MOVABLE_REF> {
    // Rvalue reference is forwarded as a reference to const lvalue.

    // TYPES
    typedef typename MovableRefUtil::RemoveReference<t_TYPE>::type UnrefType;
    typedef const UnrefType&                                       Type;
    typedef t_TYPE                                                 TargetType;

    // CLASS METHODS
    static TargetType forwardToTarget(Type v)
    {
        // Since rvalues are forwarded as *const* lvalues, we must cast away
        // the constness before converting to an rvalue reference.  If 't_TYPE'
        // is a const reference, then the constness will be reinstated on
        // return.

        // We split this cast up into two lines because Visual Studio 2015 and
        // early versions of Visual Studio 2017 create a temporary in the
        // one-liner.
        UnrefType& result = const_cast<UnrefType&>(v);
        return MovableRefUtil::move(result);
    }
};

template <class t_TYPE>
struct ForwardingType_Imp<t_TYPE, ForwardingType_Category::e_FUNCTION> {
    // Function type and is forwarded as function reference.

    // TYPES
    typedef t_TYPE& Type;
    typedef t_TYPE& TargetType;

    // CLASS METHODS
    static TargetType forwardToTarget(Type v)
        // Return the specified 'v' argument.
    {
        return v;
    }
};

template <class t_TYPE, size_t k_NUM_ELEMENTS>
struct ForwardingType_Imp<t_TYPE[k_NUM_ELEMENTS],
                          ForwardingType_Category::e_ARRAY> {
    // Array of known size and reference to array of known size is forwarded as
    // pointer to array element type.

    // TYPES
    typedef t_TYPE *Type;
    typedef t_TYPE (&TargetType)[k_NUM_ELEMENTS];

    // CLASS METHODS
    static TargetType forwardToTarget(Type v)
        // Return the specified 'v', cast to a reference to array.
    {
        return reinterpret_cast<TargetType>(*v);
    }
};

template <class t_TYPE>
struct ForwardingType_Imp<t_TYPE[], ForwardingType_Category::e_ARRAY> {
    // Array of unknown size and reference to array of unknown size is
    // forwarded as pointer to array element type.

    // TYPES
    typedef t_TYPE *Type;
    typedef t_TYPE (&TargetType)[];

    // CLASS METHODS
    static TargetType forwardToTarget(Type v)
        // Return the specified 'v' argument cast to a reference to array of
        // unknown size.
    {
        return reinterpret_cast<TargetType>(*v);
    }
};

template <class t_TYPE>
struct ForwardingType_Imp<t_TYPE, ForwardingType_Category::e_BASIC> {
    // Rvalue of basic type is forwarded with any cv-qualifier removed.

    // TYPES
    typedef typename bsl::remove_cv<t_TYPE>::type Type;
    typedef t_TYPE                              TargetType;

    // CLASS METHODS
    static TargetType& forwardToTarget(Type& v)
        // Return the specified 'v' argument with cv qualifiers added to match
        // the specified 'UNREF_TYPE'.  The return type is a reference to a
        // (possibly modifiable) 't_TYPE' object in order to work around
        // certain dpkg bugs where an rvalue is being forwarded to a function
        // that expects an lvalue.
    {
        return v;
    }
};

template <class t_TYPE>
struct ForwardingType_Imp<t_TYPE, ForwardingType_Category::e_CLASS> {
    // Rvalue of user type (i.e., class or union) is forwarded as a const
    // reference.

    // TYPES
    typedef ForwardingType_Imp Imp;
    typedef const t_TYPE&      Type;
#if defined(BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES)
    typedef MovableRef<t_TYPE>   TargetType;

    static TargetType forwardToTarget(Type v)
        // Return the specified 'v' argument cast to a modifiable movable
        // reference.
    {
        // Since rvalues are forwarded as *const* lvalues, we must cast away
        // the constness before converting to an rvalue reference.  If 't_TYPE'
        // is a const reference, then the constness will be reinstated on
        // return.

# if defined(BSLS_PLATFORM_CMP_MSVC)
        // We use a C-style cast because Visual Studio 2013, 2015, and early
        // versions of Visual Studio 2017 create a temporary with various
        // formulations using C++ casts.
        return MovableRefUtil::move((t_TYPE&)(v));
#else
        // However, other platforms are known to complain about casting away
        // the 'const' qualifier in 'Type' (i.e., in 'const t_TYPE&') unless a
        // 'const_cast' is explicitly used.
        return MovableRefUtil::move(const_cast<t_TYPE&>(v));
# endif
    }
#else
    typedef const t_TYPE&        TargetType;

    static TargetType forwardToTarget(Type v)
    {
        return v;
    }
#endif
};

}  // close package namespace
}  // close enterprise namespace

#ifndef BDE_OPENSOURCE_PUBLICATION  // BACKWARD_COMPATIBILITY
// ============================================================================
//                           BACKWARD COMPATIBILITY
// ============================================================================

#ifdef bslmf_ForwardingType
#undef bslmf_ForwardingType
#endif
#define bslmf_ForwardingType bslmf::ForwardingType
    // !DEPRECATED! This alias is defined for backward compatibility.
#endif  // BDE_OPENSOURCE_PUBLICATION -- BACKWARD_COMPATIBILITY

#ifdef bslmf_ConstForwardingType
#undef bslmf_ConstForwardingType
#endif
// BDE_VERIFY pragma: -SLM01 // Allow non-standard macro to leak from header
#define bslmf_ConstForwardingType bslmf::ConstForwardingType
    // !DEPRECATED! This alias is defined for backward compatibility.

// BDE_VERIFY pragma: pop // Restore bde_verify rules

#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 ----------------------------------