// bslmf_addreference.h                                               -*-C++-*-
#ifndef INCLUDED_BSLMF_ADDREFERENCE
#define INCLUDED_BSLMF_ADDREFERENCE

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

//@PURPOSE: Provide a meta-function for adding "reference-ness" to a type.
//
//@CLASSES:
//  bslmf::AddReference: meta-function to form a reference to a type
//
//@DESCRIPTION: This component defines a simple template 'struct',
// 'bslmf::AddReference', that is used to define a reference type from the type
// supplied as its single template type parameter.  Types that are 'void' or
// already reference types are unmodified.
//
///Usage
///-----
// This section illustrates intended use of this component.
//
///Example 1: A Simple Wrapper Class
///- - - - - - - - - - - - - - - - -
// First, let us write a simple class that can wrap any other type:
//..
//  template <class t_TYPE>
//  class Wrapper {
//    private:
//      // DATA
//      t_TYPE d_data;
//
//    public:
//      // TYPES
//      typedef typename bslmf::AddReference<t_TYPE>::Type WrappedType;
//
//      // CREATORS
//      Wrapper(t_TYPE value) : d_data(value) {}                    // IMPLICIT
//          // Create a 'Wrapper' object having the specified 'value'.
//
//      //! ~Wrapper() = default;
//          // Destroy this object.
//..
// Then, we would like to expose access to the wrapped element through a method
// that returns a reference to the data member 'd_data'.  However, there would
// be a problem if the user supplied a parameterized type 't_TYPE' that is a
// reference type, as references-to-references were not permitted by the
// language (prior the C++11 standard).  We can resolve such problems using the
// meta-function 'bslmf::AddReference'.
//..
//  // MANIPULATORS
//  typename bslmf::AddReference<t_TYPE>::Type value()
//  {
//      return d_data;
//  }
//..
// Next, we supply an accessor function, 'value', that similarly wraps the
// parameterized type 't_TYPE' with the 'bslmf::AddReference' meta-function.
// In this case we must remember to const-quality 't_TYPE' before passing it on
// to the meta-function.
//..
//      // ACCESSORS
//      typename bslmf::AddReference<const t_TYPE>::Type value() const
//      {
//          return d_data;
//      }
//  };
//..
// Now, we write a test function, 'runTest', to verify our simple wrapper type.
// We start by wrapping a simple 'int' value:
//..
//  void runTests()
//  {
//      int i = 42;
//
//      Wrapper<int> ti(i);  const Wrapper<int>& TI = ti;
//      assert(42 == i);
//      assert(42 == TI.value());
//
//      ti.value() = 13;
//      assert(42 == i);
//      assert(13 == TI.value());
//..
// Finally, we test 'Wrapper' with a reference type:
//..
//      Wrapper<int&> tr(i);  const Wrapper<int&>& TR = tr;
//      assert(42 == i);
//      assert(42 == TR.value());
//
//      tr.value() = 13;
//      assert(13 == i);
//      assert(13 == TR.value());
//
//      i = 42;
//      assert(42 == i);
//      assert(42 == TR.value());
//  }
//..
//
///Example 2: Expected Results
///- - - - - - - - - - - - - -
// For this example, the associated comments below indicate the expected type
// of 'bslmf::AddReference::Type' for a broad range of parameterized types:
//..
//  struct MyType {};
//  typedef MyType& MyTypeRef;
//
//  bslmf::AddReference<int             >::Type x1; // int&
//  bslmf::AddReference<int&            >::Type x2; // int&
//  bslmf::AddReference<int volatile    >::Type x3; // volatile int&
//  bslmf::AddReference<int volatile&   >::Type x4; // volatile int&
//
//  bslmf::AddReference<MyType          >::Type     // MyType&
//  bslmf::AddReference<MyType&         >::Type     // MyType&
//  bslmf::AddReference<MyTypeRef       >::Type     // MyType&
//  bslmf::AddReference<MyType const    >::Type     // const MyType&
//  bslmf::AddReference<MyType const&   >::Type     // const MyType&
//  bslmf::AddReference<const MyTypeRef >::Type     // MyType&
//  bslmf::AddReference<const MyTypeRef&>::Type     // MyType& (REQUIRES C++11)
//
//  bslmf::AddReference<void            >::Type     // void
//  bslmf::AddReference<void *          >::Type     // void *&
//..

#include <bslscm_version.h>

#include <bslmf_addlvaluereference.h>

namespace BloombergLP {

namespace bslmf {

                        // ===================
                        // struct AddReference
                        // ===================

template <class t_TYPE>
struct AddReference {
    // This meta-function class defines a typedef, 'Type', that is an alias for
    // a reference to the parameterized 't_TYPE'.  References to cv-qualified
    // 'void' will produce the original 'void' type and not a reference (see
    // specializations below).  References-to-references "collapse" to produce
    // an alias to the original reference type, which is the revised rule
    // according to the C++11 standard.  Note that there is no requirement that
    // the parameterized 't_TYPE' be a complete type.

    typedef typename bsl::add_lvalue_reference<t_TYPE>::type Type;
};

}  // close package namespace

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

#ifdef bslmf_AddReference
#undef bslmf_AddReference
#endif
#define bslmf_AddReference bslmf::AddReference
    // This alias is defined for backward compatibility.
#endif  // BDE_OPENSOURCE_PUBLICATION -- BACKWARD_COMPATIBILITY

}  // close enterprise namespace

#endif

// ----------------------------------------------------------------------------
// Copyright 2013 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 ----------------------------------