<commit_before>// bslmf_forwardingtype.t.cpp                                         -*-C++-*-
#include <bslmf_forwardingtype.h>

#include <bslmf_isarray.h>
#include <bslmf_issame.h>          // for testing only

#include <bsls_platform.h>
#include <bsls_bsltestutil.h>

#include <stdio.h>     // atoi()
#include <stdlib.h>    // atoi()

using namespace BloombergLP;

// Suppress messages about all-uppercase type names.  Test drivers are rife
// with short names like 'F' or 'PF' or 'T' or 'T1'.

// BDE_VERIFY pragma: -UC01

// ============================================================================
//                                TEST PLAN
// ----------------------------------------------------------------------------
//                                Overview
//                                --------
// This component provides a meta-function.  We simply verify that it returns
// the proper type for a list of suitably chosen arguments.  It also provides a
// utility function for which we verify that it returns the correct type and
// value.  Finally, we perform an end-to-end test that exercises the intended
// use of the component in order to verify that it is actually useful as
// specified.
// ----------------------------------------------------------------------------
// [ 2] ForwardingType<TYPE>::Type
// [ 3] ForwardingTypeUtil<TYPE>::TargetType
// [ 3] ForwardingTypeUtil<TYPE>::forwardToTarget(v)
// ----------------------------------------------------------------------------
// [ 4] END-TO-END OVERLOADING
// [ 5] USAGE EXAMPLES
// [ 1] CvRefMatch<T>::operator()()
// [ 1] CvArrayMatch<T>::operator()()
// [ 1] FuncMatch<F>::operator()()

// ============================================================================
//                     STANDARD BSL ASSERT TEST FUNCTION
// ----------------------------------------------------------------------------

namespace {

int testStatus = 0;

void aSsErT(bool condition, const char *message, int line)
{
    if (condition) {
        printf("Error " __FILE__ "(%d): %s    (failed)\n", line, message);

        if (0 <= testStatus && testStatus <= 100) {
            ++testStatus;
        }
    }
}

}  // close unnamed namespace

// ============================================================================
//               STANDARD BSL TEST DRIVER MACRO ABBREVIATIONS
// ----------------------------------------------------------------------------

#define ASSERT       BSLS_BSLTESTUTIL_ASSERT
#define ASSERTV      BSLS_BSLTESTUTIL_ASSERTV

#define LOOP_ASSERT  BSLS_BSLTESTUTIL_LOOP_ASSERT
#define LOOP0_ASSERT BSLS_BSLTESTUTIL_LOOP0_ASSERT
#define LOOP1_ASSERT BSLS_BSLTESTUTIL_LOOP1_ASSERT
#define LOOP2_ASSERT BSLS_BSLTESTUTIL_LOOP2_ASSERT
#define LOOP3_ASSERT BSLS_BSLTESTUTIL_LOOP3_ASSERT
#define LOOP4_ASSERT BSLS_BSLTESTUTIL_LOOP4_ASSERT
#define LOOP5_ASSERT BSLS_BSLTESTUTIL_LOOP5_ASSERT
#define LOOP6_ASSERT BSLS_BSLTESTUTIL_LOOP6_ASSERT

#define Q            BSLS_BSLTESTUTIL_Q   // Quote identifier literally.
#define P            BSLS_BSLTESTUTIL_P   // Print identifier and value.
#define P_           BSLS_BSLTESTUTIL_P_  // P(X) without '\n'.
#define T_           BSLS_BSLTESTUTIL_T_  // Print a tab (w/o newline).
#define L_           BSLS_BSLTESTUTIL_L_  // current Line number

// ============================================================================
//               ADDITIONAL MACROS FOR THIS TEST DRIVER
// ----------------------------------------------------------------------------

#define ASSERT_SAME(X, Y) ASSERT((bsl::is_same<X, Y>::value))

//=============================================================================
//                  GLOBAL TYPES/OBJECTS FOR TESTING
//-----------------------------------------------------------------------------

enum   Enum   { e_VAL1 = 1, e_VAL2 };

struct Struct {
    int d_data;

    explicit Struct(int v) : d_data(v) { }
        // Construct from the specified 'v'.

    Struct(Struct& other) : d_data(other.d_data) { }
    Struct(const Struct& other) : d_data(other.d_data) { }
    Struct(volatile Struct& other) : d_data(other.d_data) { }
    Struct(const volatile Struct& other) : d_data(other.d_data) { }
        // Copy-construct from the specified 'other'.
};

inline bool operator==(Struct a, Struct b)
    // Return true if the specified 'a' and 'b' objects have same data member
    // value.
{
    return a.d_data == b.d_data;
}

union  Union  {
    int d_data;

    explicit Union(int v) : d_data(v) { }
        // Construct from the specified 'v'.

    Union(Union& other) : d_data(other.d_data) { }
    Union(const Union& other) : d_data(other.d_data) { }
    Union(volatile Union& other) : d_data(other.d_data) { }
    Union(const volatile Union& other) : d_data(other.d_data) { }
        // Copy-construct from the specified 'other'.
};

inline bool operator==(Union a, Union b)
    // Return true if the specified 'a' and 'b' objects have the same data
    // member value.
{
    return a.d_data == b.d_data;
}

class  Class  {
    int d_data;
public:
    explicit Class(int v) : d_data(v) { }
        // Construct from the specified 'v'.

    Class(Class& other) : d_data(other.d_data) { }
    Class(const Class& other) : d_data(other.d_data) { }
    Class(volatile Class& other) : d_data(other.d_data) { }
    Class(const volatile Class& other) : d_data(other.d_data) { }
        // Copy-construct from the specified 'other'.

    int value() const { return d_data; }
        // Return the value of this object.
};

inline bool operator==(Class a, Class b)
    // Return true if the specified 'a' and 'b' have the same 'value()'.
{
    return a.value() == b.value();
}

typedef void      F ();
typedef void (*  PF)();

typedef void    Fi  (int);
typedef void    FRi (int&);

typedef char    A [5];
typedef char   AU [];

typedef int Struct::*Pm;
typedef int (Class::*Pmf)() const;

void func() { }
    // Noop function that takes no arguments and returns nothing.

void funcI(int) { }
    // Noop function that takes one by-value argument and returns nothing.

void funcRi(int&) { }
    // Noop function that takes one by-reference argument and returns nothing.

enum {
    k_LVALUE,
    k_CONST_LVALUE,
    k_VOLATILE_LVALUE,
    k_CONST_VOLATILE_LVALUE,
    k_RVALUE,
    k_CONST_RVALUE,
    k_VOLATILE_RVALUE,
    k_CONST_VOLATILE_RVALUE,
    k_FUNC_POINTER,
    k_FUNC_REFERENCE
};

template <class TP>
TP toRvalue(TP v)
    // Return a copy of the specified 'v' object.  If 'TP' has a cv-qualifier,
    // then the compiler might discard it in the return type.  For testing
    // purposes, what is important is that we get exactly what we would get
    // when returning an object of type 'TP'.
{
    return v;
}

template <class TP>
struct CvRefMatch {
    // Function object type that can be invoked with a cv-qualified reference
    // to an object of the specified 'TP' parameter type.

    int operator()(TP&) const { return k_LVALUE; }
    int operator()(const TP&) const { return k_CONST_LVALUE; }
    int operator()(volatile TP&) const { return k_VOLATILE_LVALUE; }
    int operator()(const volatile TP&) const { return k_CONST_VOLATILE_LVALUE;}
        // Invoke with an l-value reference.

#if defined(BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES)
    int operator()(TP&&) const { return k_RVALUE; }
    int operator()(const TP&&) const { return k_CONST_RVALUE; }
    int operator()(volatile TP&&) const { return k_VOLATILE_RVALUE; }
    int operator()(const volatile TP&&) const
        // Invoke with an r-value reference.
        { return k_CONST_VOLATILE_RVALUE; }
#endif
};

template <class TP>
class CvArrayMatch {
    // Function object type that can be invoked with an array of the specified
    // 'TP' parameter type.

    template <size_t k_SZ>
    int match(TP (&)[k_SZ], int) const { return int(k_SZ); }
        // Matches an array of known size.

    int match(TP [], ...) const { return 0; }
        // Matches an array of unknown size.

public:

#if defined(BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES)
    template <class ANY>
    int operator()(ANY&& a) const { return match(a, 0); }
        // Matches both lvalue and rvalue arrays.
#else
    template <class ANY>
    int operator()(ANY& a) const { return match(a, 0); }
#endif
};

template <class FUNC> struct FuncMatch;

template <class FUNC>
struct FuncMatch {
    // Function object type that can be invoked with a function, function
    // pointer, or function reference.

    struct MatchFuncPtr {
        // Class that is convertible from 'FUNC *'
        MatchFuncPtr(FUNC *) { }                                    // IMPLICIT
            // Convert a 'FUNC *' pointer to a 'MatchFuncPtr' object.
    };

    int operator()(FUNC&) const { return k_FUNC_REFERENCE; }
        // Match a function or a function reference.

    int operator()(MatchFuncPtr) const { return k_FUNC_POINTER; }
        // Match function pointer.  This overload requires a user-defined
        // conversion and this is less prefered than the previous one for
        // arguments that match both.
};

template <class TP, class INVOCABLE>
int endToEndIntermediary(typename bslmf::ForwardingType<TP>::Type arg,
                         const INVOCABLE& target)
    // Forward the specified 'arg' to the specified 'target'.  This function is
    // called in the middle of a chain of function calls that forward to the
    // eventual 'target' invocable object.
{
    return target(bslmf::ForwardingTypeUtil<TP>::forwardToTarget(arg));
}

template <class TP, class INVOCABLE>
int testEndToEnd(TP arg, const INVOCABLE& target)
    // Forward the specified 'arg' to the specified 'target' via an
    // intermediate function.  This function is called at the start of a chain
    // of function callss that forward to the eventual 'target' invocable
    // object.
{
    return endToEndIntermediary<TP>(arg, target);
}

//=============================================================================
//                           USAGE EXAMPLES
//-----------------------------------------------------------------------------

///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 usageExample1()
        // 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                    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;

        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));
    }
//..
//
///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) { }

        RET operator()(ARG1, ARG2, ARG3) const;
            // Invoke the stored function pointer with the specified 'ARG1',
            // 'ARG2', and 'ARG3' arguments, logging the invocation and
            // returning the result of the function pointer invocation.
//..
// Next, we declare a private member function that actually invokes the
// wrapped function. This member function will be called by 'operator()' and
// must therefore receive arguments indirectly through 'operator()'. In order
// to avoid excessive copies of pass-by-value arguments, we use
// 'ForwardingType' to declare a more efficient intermediate argument type for
// our private member function:
//..
    private:
        RET invoke(typename bslmf::ForwardingType<ARG1>::Type a1,
                   typename bslmf::ForwardingType<ARG2>::Type a2,
                   typename bslmf::ForwardingType<ARG3>::Type a3) const;
            // Invoke the wrapped function with the specified 'a1', 'a2', and
            // 'a3' arguments and return the result of the 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 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.
//..
// Next, we implement 'operator()' to call the logging functions and then call
// 'invoke':
//..
    template <class RET, class ARG1, class ARG2, class ARG3>
    RET LoggingWrapper<RET(ARG1, ARG2, ARG3)>::operator()(ARG1 a1,
                                                          ARG2 a2,
                                                          ARG3 a3) const {
        logInvocation(a1);
        RET r = invoke(a1, a2, a3);
        logReturn(a1);
        return r;
    }
//..
// Next, we implement 'invoke' to actually call the 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)>::invoke(
        typename bslmf::ForwardingType<ARG1>::Type a1,
        typename bslmf::ForwardingType<ARG2>::Type a2,
        typename bslmf::ForwardingType<ARG3>::Type a3) const
    {
        return d_function_p(
            bslmf::ForwardingTypeUtil<ARG1>::forwardToTarget(a1),
            bslmf::ForwardingTypeUtil<ARG2>::forwardToTarget(a2),
            bslmf::ForwardingTypeUtil<ARG3>::forwardToTarget(a3));
    }
//..
// Next, 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
            // intial value of this 'ArgType' object, otherwise this object
            // will hold the value 0.

        ArgType(const ArgType& original)
            // Copy-construct from 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(2, x, y);  // Expect two copies of 'y'
        ASSERT(1 == invocations && 1 == returns);
        ASSERT(99 == x.value());
    }
//..

//=============================================================================
//                              MAIN PROGRAM
//-----------------------------------------------------------------------------

template <class TYPE>
bool sameAddress(const TYPE& a, const TYPE& b)
    // Return true if address of the specified 'a' object matches the address
    // of the specified 'b' object.  Unlike a direct test, this function can be
    // called even if 'a' or 'b' is an rvalue or rvalue refearence.
{
    return &a == &b;
}

template <class TYPE>
void testForwardToTargetVal(TYPE obj)
    // Test 'forwardToTarget' when the specified 'obj' is an rvalue.
{
    typedef typename bslmf::ForwardingType<TYPE>::Type FwdType;
    typedef typename bslmf::ForwardingTypeUtil<TYPE>::TargetType TargetType;

#if defined(BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES)
    ASSERT_SAME(TYPE, typename bsl::remove_reference<TargetType>::type);
#else
    ASSERT((bsl::is_same<TYPE,
                    typename bsl::remove_reference<TargetType>::type>::value ||
            bsl::is_same<const TYPE,
                    typename bsl::remove_reference<TargetType>::type>::value));
#endif

    FwdType fwdObj = obj;

    // For pass-by-value, compare original and final value.
    ASSERT(obj == bslmf::ForwardingTypeUtil<TYPE>::forwardToTarget(fwdObj));
}

template <class TYPE>
void testForwardToTargetArray(TYPE obj)
    // Test 'forwardToTarget' when the specified 'obj' is an array.
{
    typedef typename bslmf::ForwardingType<TYPE>::Type FwdType;
    typedef typename bslmf::ForwardingTypeUtil<TYPE>::TargetType TargetType;

    ASSERT_SAME(TYPE&, TargetType);

    FwdType fwdObj = obj;

    // For arrays, compare address of first element of original and final
    // arrays.
    ASSERT(&obj[0] ==
           &bslmf::ForwardingTypeUtil<TYPE>::forwardToTarget(fwdObj)[0]);
}

template <class TYPE>
void testForwardToTargetRef(TYPE ref)
    // Test 'forwardToTarget' when the specified 'ref' is a reference type.
{
    typedef typename bslmf::ForwardingType<TYPE>::Type FwdType;
    typedef typename bslmf::ForwardingTypeUtil<TYPE>::TargetType TargetType;

    ASSERT_SAME(TYPE, TargetType);

    FwdType fwdRef = ref;

    // For pass-by-reference, compare addresses of original and final
    // references.
    ASSERT(sameAddress(ref,
                    bslmf::ForwardingTypeUtil<TYPE>::forwardToTarget(fwdRef)));
}<commit_msg>Fix forwarding type test driver on gcc 4.1.2<commit_after>// bslmf_forwardingtype.t.cpp                                         -*-C++-*-
#include <bslmf_forwardingtype.h>

#include <bslmf_addlvaluereference.h>
#include <bslmf_isarray.h>
#include <bslmf_issame.h>          // for testing only

#include <bsls_platform.h>
#include <bsls_bsltestutil.h>

#include <stdio.h>     // atoi()
#include <stdlib.h>    // atoi()

using namespace BloombergLP;

// Suppress messages about all-uppercase type names.  Test drivers are rife
// with short names like 'F' or 'PF' or 'T' or 'T1'.

// BDE_VERIFY pragma: -UC01

// ============================================================================
//                                TEST PLAN
// ----------------------------------------------------------------------------
//                                Overview
//                                --------
// This component provides a meta-function.  We simply verify that it returns
// the proper type for a list of suitably chosen arguments.  It also provides a
// utility function for which we verify that it returns the correct type and
// value.  Finally, we perform an end-to-end test that exercises the intended
// use of the component in order to verify that it is actually useful as
// specified.
// ----------------------------------------------------------------------------
// [ 2] ForwardingType<TYPE>::Type
// [ 3] ForwardingTypeUtil<TYPE>::TargetType
// [ 3] ForwardingTypeUtil<TYPE>::forwardToTarget(v)
// ----------------------------------------------------------------------------
// [ 4] END-TO-END OVERLOADING
// [ 5] USAGE EXAMPLES
// [ 1] CvRefMatch<T>::operator()()
// [ 1] CvArrayMatch<T>::operator()()
// [ 1] FuncMatch<F>::operator()()

// ============================================================================
//                     STANDARD BSL ASSERT TEST FUNCTION
// ----------------------------------------------------------------------------

namespace {

int testStatus = 0;

void aSsErT(bool condition, const char *message, int line)
{
    if (condition) {
        printf("Error " __FILE__ "(%d): %s    (failed)\n", line, message);

        if (0 <= testStatus && testStatus <= 100) {
            ++testStatus;
        }
    }
}

}  // close unnamed namespace

// ============================================================================
//               STANDARD BSL TEST DRIVER MACRO ABBREVIATIONS
// ----------------------------------------------------------------------------

#define ASSERT       BSLS_BSLTESTUTIL_ASSERT
#define ASSERTV      BSLS_BSLTESTUTIL_ASSERTV

#define LOOP_ASSERT  BSLS_BSLTESTUTIL_LOOP_ASSERT
#define LOOP0_ASSERT BSLS_BSLTESTUTIL_LOOP0_ASSERT
#define LOOP1_ASSERT BSLS_BSLTESTUTIL_LOOP1_ASSERT
#define LOOP2_ASSERT BSLS_BSLTESTUTIL_LOOP2_ASSERT
#define LOOP3_ASSERT BSLS_BSLTESTUTIL_LOOP3_ASSERT
#define LOOP4_ASSERT BSLS_BSLTESTUTIL_LOOP4_ASSERT
#define LOOP5_ASSERT BSLS_BSLTESTUTIL_LOOP5_ASSERT
#define LOOP6_ASSERT BSLS_BSLTESTUTIL_LOOP6_ASSERT

#define Q            BSLS_BSLTESTUTIL_Q   // Quote identifier literally.
#define P            BSLS_BSLTESTUTIL_P   // Print identifier and value.
#define P_           BSLS_BSLTESTUTIL_P_  // P(X) without '\n'.
#define T_           BSLS_BSLTESTUTIL_T_  // Print a tab (w/o newline).
#define L_           BSLS_BSLTESTUTIL_L_  // current Line number

// ============================================================================
//               ADDITIONAL MACROS FOR THIS TEST DRIVER
// ----------------------------------------------------------------------------

#define ASSERT_SAME(X, Y) ASSERT((bsl::is_same<X, Y>::value))

//=============================================================================
//                  GLOBAL TYPES/OBJECTS FOR TESTING
//-----------------------------------------------------------------------------

enum   Enum   { e_VAL1 = 1, e_VAL2 };

struct Struct {
    int d_data;

    explicit Struct(int v) : d_data(v) { }
        // Construct from the specified 'v'.

    Struct(Struct& other) : d_data(other.d_data) { }
    Struct(const Struct& other) : d_data(other.d_data) { }
    Struct(volatile Struct& other) : d_data(other.d_data) { }
    Struct(const volatile Struct& other) : d_data(other.d_data) { }
        // Copy-construct from the specified 'other'.
};

inline bool operator==(Struct a, Struct b)
    // Return true if the specified 'a' and 'b' objects have same data member
    // value.
{
    return a.d_data == b.d_data;
}

union  Union  {
    int d_data;

    explicit Union(int v) : d_data(v) { }
        // Construct from the specified 'v'.

    Union(Union& other) : d_data(other.d_data) { }
    Union(const Union& other) : d_data(other.d_data) { }
    Union(volatile Union& other) : d_data(other.d_data) { }
    Union(const volatile Union& other) : d_data(other.d_data) { }
        // Copy-construct from the specified 'other'.
};

inline bool operator==(Union a, Union b)
    // Return true if the specified 'a' and 'b' objects have the same data
    // member value.
{
    return a.d_data == b.d_data;
}

class  Class  {
    int d_data;
public:
    explicit Class(int v) : d_data(v) { }
        // Construct from the specified 'v'.

    Class(Class& other) : d_data(other.d_data) { }
    Class(const Class& other) : d_data(other.d_data) { }
    Class(volatile Class& other) : d_data(other.d_data) { }
    Class(const volatile Class& other) : d_data(other.d_data) { }
        // Copy-construct from the specified 'other'.

    int value() const { return d_data; }
        // Return the value of this object.
};

inline bool operator==(Class a, Class b)
    // Return true if the specified 'a' and 'b' have the same 'value()'.
{
    return a.value() == b.value();
}

typedef void      F ();
typedef void (*  PF)();

typedef void    Fi  (int);
typedef void    FRi (int&);

typedef char    A [5];
typedef char   AU [];

typedef int Struct::*Pm;
typedef int (Class::*Pmf)() const;

void func() { }
    // Noop function that takes no arguments and returns nothing.

void funcI(int) { }
    // Noop function that takes one by-value argument and returns nothing.

void funcRi(int&) { }
    // Noop function that takes one by-reference argument and returns nothing.

enum {
    k_LVALUE,
    k_CONST_LVALUE,
    k_VOLATILE_LVALUE,
    k_CONST_VOLATILE_LVALUE,
    k_RVALUE,
    k_CONST_RVALUE,
    k_VOLATILE_RVALUE,
    k_CONST_VOLATILE_RVALUE,
    k_FUNC_POINTER,
    k_FUNC_REFERENCE
};

template <class TP>
TP toRvalue(TP v)
    // Return a copy of the specified 'v' object.  If 'TP' has a cv-qualifier,
    // then the compiler might discard it in the return type.  For testing
    // purposes, what is important is that we get exactly what we would get
    // when returning an object of type 'TP'.
{
    return v;
}

template <class TP>
struct CvRefMatch {
    // Function object type that can be invoked with a cv-qualified reference
    // to an object of the specified 'TP' parameter type.

    int operator()(TP&) const { return k_LVALUE; }
    int operator()(const TP&) const { return k_CONST_LVALUE; }
    int operator()(volatile TP&) const { return k_VOLATILE_LVALUE; }
    int operator()(const volatile TP&) const { return k_CONST_VOLATILE_LVALUE;}
        // Invoke with an l-value reference.

#if defined(BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES)
    int operator()(TP&&) const { return k_RVALUE; }
    int operator()(const TP&&) const { return k_CONST_RVALUE; }
    int operator()(volatile TP&&) const { return k_VOLATILE_RVALUE; }
    int operator()(const volatile TP&&) const
        // Invoke with an r-value reference.
        { return k_CONST_VOLATILE_RVALUE; }
#endif
};

template <class TP>
class CvArrayMatch {
    // Function object type that can be invoked with an array of the specified
    // 'TP' parameter type.

    template <size_t k_SZ>
    int match(TP (&)[k_SZ], int) const { return int(k_SZ); }
        // Matches an array of known size.

    int match(TP [], ...) const { return 0; }
        // Matches an array of unknown size.

public:

#if defined(BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES)
    template <class ANY>
    int operator()(ANY&& a) const { return match(a, 0); }
        // Matches both lvalue and rvalue arrays.
#else
    template <class ANY>
    int operator()(ANY& a) const { return match(a, 0); }
#endif
};

template <class FUNC> struct FuncMatch;

template <class FUNC>
struct FuncMatch {
    // Function object type that can be invoked with a function, function
    // pointer, or function reference.

    struct MatchFuncPtr {
        // Class that is convertible from 'FUNC *'
        MatchFuncPtr(FUNC *) { }                                    // IMPLICIT
            // Convert a 'FUNC *' pointer to a 'MatchFuncPtr' object.
    };

    int operator()(FUNC&) const { return k_FUNC_REFERENCE; }
        // Match a function or a function reference.

    int operator()(MatchFuncPtr) const { return k_FUNC_POINTER; }
        // Match function pointer.  This overload requires a user-defined
        // conversion and this is less prefered than the previous one for
        // arguments that match both.
};

template <class TP, class INVOCABLE>
int endToEndIntermediary(typename bslmf::ForwardingType<TP>::Type arg,
                         const INVOCABLE& target)
    // Forward the specified 'arg' to the specified 'target'.  This function is
    // called in the middle of a chain of function calls that forward to the
    // eventual 'target' invocable object.
{
    return target(bslmf::ForwardingTypeUtil<TP>::forwardToTarget(arg));
}

template <class TP, class INVOCABLE>
int testEndToEnd(TP arg, const INVOCABLE& target)
    // Forward the specified 'arg' to the specified 'target' via an
    // intermediate function.  This function is called at the start of a chain
    // of function callss that forward to the eventual 'target' invocable
    // object.
{
    return endToEndIntermediary<TP>(arg, target);
}

//=============================================================================
//                           USAGE EXAMPLES
//-----------------------------------------------------------------------------

///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 usageExample1()
        // 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                    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;

        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));
    }
//..
//
///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) { }

        RET operator()(ARG1, ARG2, ARG3) const;
            // Invoke the stored function pointer with the specified 'ARG1',
            // 'ARG2', and 'ARG3' arguments, logging the invocation and
            // returning the result of the function pointer invocation.
//..
// Next, we declare a private member function that actually invokes the
// wrapped function. This member function will be called by 'operator()' and
// must therefore receive arguments indirectly through 'operator()'. In order
// to avoid excessive copies of pass-by-value arguments, we use
// 'ForwardingType' to declare a more efficient intermediate argument type for
// our private member function:
//..
    private:
        RET invoke(typename bslmf::ForwardingType<ARG1>::Type a1,
                   typename bslmf::ForwardingType<ARG2>::Type a2,
                   typename bslmf::ForwardingType<ARG3>::Type a3) const;
            // Invoke the wrapped function with the specified 'a1', 'a2', and
            // 'a3' arguments and return the result of the 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 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.
//..
// Next, we implement 'operator()' to call the logging functions and then call
// 'invoke':
//..
    template <class RET, class ARG1, class ARG2, class ARG3>
    RET LoggingWrapper<RET(ARG1, ARG2, ARG3)>::operator()(ARG1 a1,
                                                          ARG2 a2,
                                                          ARG3 a3) const {
        logInvocation(a1);
        RET r = invoke(a1, a2, a3);
        logReturn(a1);
        return r;
    }
//..
// Next, we implement 'invoke' to actually call the 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)>::invoke(
        typename bslmf::ForwardingType<ARG1>::Type a1,
        typename bslmf::ForwardingType<ARG2>::Type a2,
        typename bslmf::ForwardingType<ARG3>::Type a3) const
    {
        return d_function_p(
            bslmf::ForwardingTypeUtil<ARG1>::forwardToTarget(a1),
            bslmf::ForwardingTypeUtil<ARG2>::forwardToTarget(a2),
            bslmf::ForwardingTypeUtil<ARG3>::forwardToTarget(a3));
    }
//..
// Next, 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
            // intial value of this 'ArgType' object, otherwise this object
            // will hold the value 0.

        ArgType(const ArgType& original)
            // Copy-construct from 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(2, x, y);  // Expect two copies of 'y'
        ASSERT(1 == invocations && 1 == returns);
        ASSERT(99 == x.value());
    }
//..

//=============================================================================
//                              MAIN PROGRAM
//-----------------------------------------------------------------------------

template <class TYPE>
bool sameAddress(const TYPE& a, const TYPE& b)
    // Return true if address of the specified 'a' object matches the address
    // of the specified 'b' object.  Unlike a direct test, this function can be
    // called even if 'a' or 'b' is an rvalue or rvalue refearence.
{
    return &a == &b;
}

template <class TYPE>
void testForwardToTargetVal(TYPE obj)
    // Test 'forwardToTarget' when the specified 'obj' is an rvalue.
{
    typedef typename bslmf::ForwardingType<TYPE>::Type FwdType;
    typedef typename bslmf::ForwardingTypeUtil<TYPE>::TargetType TargetType;

#if defined(BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES)
    ASSERT_SAME(TYPE, typename bsl::remove_reference<TargetType>::type);
#else
    ASSERT((bsl::is_same<TYPE,
                    typename bsl::remove_reference<TargetType>::type>::value ||
            bsl::is_same<const TYPE,
                    typename bsl::remove_reference<TargetType>::type>::value));
#endif

    FwdType fwdObj = obj;

    // For pass-by-value, compare original and final value.
    ASSERT(obj == bslmf::ForwardingTypeUtil<TYPE>::forwardToTarget(fwdObj));
}

template <class TYPE>
void testForwardToTargetArray(TYPE obj)
    // Test 'forwardToTarget' when the specified 'obj' is an array.
{
    typedef typename bslmf::ForwardingType<TYPE>::Type FwdType;
    typedef typename bslmf::ForwardingTypeUtil<TYPE>::TargetType TargetType;

    typedef typename bsl::add_lvalue_reference<TYPE>::Type RefType;
                            // gcc 4.1.2 does not support reference collapsing.
    ASSERT_SAME(RefType, TargetType);

    FwdType fwdObj = obj;

    // For arrays, compare address of first element of original and final
    // arrays.
    ASSERT(&obj[0] ==
           &bslmf::ForwardingTypeUtil<TYPE>::forwardToTarget(fwdObj)[0]);
}

template <class TYPE>
void testForwardToTargetRef(TYPE ref)
    // Test 'forwardToTarget' when the specified 'ref' is a reference type.
{
    typedef typename bslmf::ForwardingType<TYPE>::Type FwdType;
    typedef typename bslmf::ForwardingTypeUtil<TYPE>::TargetType TargetType;

    ASSERT_SAME(TYPE, TargetType);

    FwdType fwdRef = ref;

    // For pass-by-reference, compare addresses of original and final
    // references.
    ASSERT(sameAddress(ref,
                    bslmf::ForwardingTypeUtil<TYPE>::forwardToTarget(fwdRef)));
}
{'fraction_non_alphanumeric': 0.1635287152161042, 'fraction_numerical': 0.008099467140319715, 'mean_word_length': 2.366767660660182, 'pattern_counts': {'":': 0, '<': 173, '<?xml version=': 0, '>': 169, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 29, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1876377', 'n_tokens_mistral': 12485, 'n_tokens_neox': 12037, 'n_words': 3890}