// bsls_nullptr.h                                                     -*-C++-*-
#ifndef INCLUDED_BSLS_NULLPTR
#define INCLUDED_BSLS_NULLPTR

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

//@PURPOSE: Provide a distinct type for null pointer literals.
//
//@CLASSES:
//   bsl::nullptr_t: type for function parameter to match null pointer literals
//
//@DESCRIPTION: This component provides 'bsl::nullptr_t' as a limited emulation
// of the C++11 type, 'std::nullptr_t', which can be used as a function
// parameter type to create an overload set where null pointer literals are
// handled specially.  Note that this component will be deprecated, and
// ultimately removed, once BDE code can assume support for a C++11 compiler.
// On a platform that supports the language feature, a fully-conforming
// 'typedef' is supplied rather than using the emulation layer.
//
///Limitations
///-----------
// This component provides a simple emulation of the C++11 facility, which
// cannot be expressed with a pure library solution.  As such it comes with a
// number of limitations.  The most obvious is that C++11 provides a new null
// pointer literal, 'nullptr', which is not emulated by this component.  The
// new null pointer literal is an object of a new type, expressed by the alias
// 'nullptr_t', which this component emulates.  However, as this is a
// library-only emulation, it does not have any preference in the overloading
// rules, so will be an equal-rank ambiguous match.  For example, given the
// following overload set, a call to 'myFunction' with a null pointer literal
// would be ambiguous:
//..
//  void myFunction(void *p);
//  void myFunction(bsl::nullptr_t);
//
//  int main() {
//     myFunction(0);  // ERROR, ambiguous function call
//  }
//..
// However, if the pointer-argument is a pointer whose type is deduced from the
// function call, then no pointer type can be deduced from the null pointer and
// this component becomes necessary.
//..
//  template<typename T>
//  void myFunction(T *p);
//  void myFunction(bsl::nullptr_t);
//
//  int main() {
//     myFunction(0);  // call the 'bsl::nullptr_t' method
//  }
//..
// Null pointer values can be created in C++11 by creating objects of type
// 'std::nullptr_t', and then used to initialize pointer and pointer-to-member
// objects:
//..
//  std::nullptr_t nullLiteral = std::nullptr_t();
//  int *pI = nullLiteral;
//..
// The type of a 'bsl::nullptr_t' object cannot be used in such assignments or
// initializations, unless compiled on a platform that natively supports this
// C++11 language feature.
//
///Usage
///-----
// This section illustrates intended use of this component.
//
// Example 1: Constructing a "smart pointer"
// - - - - - - - - - - - - - - - - - - - - -
// First we define a smart pointer class template, as a guard to destroy a
// managed object as the smart pointer leaves scope.  This class will have a
// constructor template taking a pointer to a type potentially derived from
// the parameterized type of the smart pointer, and also a deletion-policy
// function.  By capturing the most-derived type through type-deduction when
// the smart pointer is constructed, we can ensure the correct destructor is
// called, even if the destructor of the base class has not been declared as
// 'virtual'.  However, relying on type-deduction means we cannot pass a null
// pointer to this constructor, as it is not possible to deduce what type a
// null pointer is supposed to refer to, therefore we must use a special null
// pointer type, such as 'bsls::nullptr_t'.  Note that in real code we would
// allocate and reclaim memory using a user-specified allocator, but defining
// such protocols in this low level component would further distract from the
// 'nullptr' usage in this example.
//..
//  template<class TARGET_TYPE>
//  class ScopedPointer {
//      // This class template is a guard to manage a dynamically created
//      // object of the parameterized 'TARGET_TYPE'.
//
//    private:
//      typedef void DeleterFn(TARGET_TYPE *);  // deleter type
//
//      // DATA
//      TARGET_TYPE *d_target_p;    // wrapped pointer
//      DeleterFn   *d_deleter_fn;  // deleter function
//
//      template<class SOURCE_TYPE>
//      static void defaultDeleteFn(TARGET_TYPE *ptr);
//          // Destroy the specified '*ptr' by calling 'delete' on the pointer
//          // cast to the parameterized 'SOURCE_TYPE*'.  It is an error to
//          // instantiate this template with a 'SOURCE_TYPE' that is not
//          // derived from (and cv-compatible with) 'TARGET_TYPE'.
//
//     private:
//      // NOT IMPLEMENTED
//      ScopedPointer(const ScopedPointer&);
//      ScopedPointer& operator=(const ScopedPointer&);
//          // Objects of this type cannot be copied.
//
//    public:
//      template<class SOURCE_TYPE>
//      ScopedPointer(SOURCE_TYPE *pointer,
//                    DeleterFn   *fn = &defaultDeleteFn<SOURCE_TYPE>);
//          // Create a 'ScopedPointer' object owning the specified 'pointer'
//          // and using the specified 'fn' to destroy the owned pointer when
//          // this object is destroyed.
//
//      ScopedPointer(bsl::nullptr_t = 0);
//          // Create an empty 'ScopedPointer' object that does not own a
//          // pointer.
//
//      ~ScopedPointer();
//          // Destroy this 'ScopedPointer' object and the target object
//          // that it owns, using the stored deleter function.
//
//      // Further methods appropriate to a smart pointer, such as
//      // 'operator*' and 'operator->' elided from this example.
//  };
//..
// Then we provide a definition for each of the methods.
//..
//  template<class TARGET_TYPE>
//  template<class SOURCE_TYPE>
//  void ScopedPointer<TARGET_TYPE>::defaultDeleteFn(TARGET_TYPE *ptr)
//  {
//      delete static_cast<SOURCE_TYPE *>(ptr);
//  }
//
//  template<class TARGET_TYPE>
//  template<class SOURCE_TYPE>
//  inline
//  ScopedPointer<TARGET_TYPE>::ScopedPointer(SOURCE_TYPE *pointer,
//                                            DeleterFn   *fn)
//  : d_target_p(pointer)
//  , d_deleter_fn(fn)
//  {
//  }
//
//  template<class TARGET_TYPE>
//  inline
//  ScopedPointer<TARGET_TYPE>::ScopedPointer(bsl::nullptr_t)
//  : d_target_p(0)
//  , d_deleter_fn(0)
//  {
//  }
//
//  template<class TARGET_TYPE>
//  inline
//  ScopedPointer<TARGET_TYPE>::~ScopedPointer()
//  {
//      if (d_deleter_fn) {
//          d_deleter_fn(d_target_p);
//      }
//  }
//..
// Finally, we can construct a 'ScopedPointer' with a null pointer literal,
// that would otherwise be non-deducible, using our 'bsl::nullptr_t' overload.
//..
//  void testScopedPointer()
//  {
//      ScopedPointer<int> x(0);
//  }
//..

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

#if defined(BSLS_COMPILERFEATURES_SUPPORT_NULLPTR)
#  if defined nullptr
#  error Some earlier header has defined the keyword 'nullptr' as a macro.
    // Occasionally we encounter code-bases predating C++11 that define a macro
    // named 'nullptr', possible trying to mimic the expected interface when
    // ported to a C++11 world.  However, it is undefined behavior to redefine
    // a keyword of the language, and typically breaks the implementation of
    // the type alias 'nullptr_t' in unusual ways, that (wrongly) report this
    // header file as the source of the problem, rather than the point at which
    // it is first observed.
#  endif

#  if !defined(BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE)
    // We currently know of no platform that supports 'nullptr' and does not
    // also support 'decltype'.  We conservatively error should such a
    // surprising platform emerge.
#  error No support for 'std::nullptr_t' unless 'decltype' is also available.
#  else
#  define BSLS_NULLPTR_USING_NATIVE_NULLPTR_T  // feature detection macro
namespace bsl {
    // We must define this 'typedef' appropriately for platforms that support
    // 'nullptr'.

#if defined(BSLS_PLATFORM_CMP_MSVC) && defined(__cplusplus_cli)
    // MSVC in /clr mode defines 'nullptr' as the .NET null pointer type, which
    // is different from C++11 'nullptr'.  To resolve this conflict MSVC
    // provides '__nullptr' for C++11 'nullptr'.

    typedef decltype(__nullptr) nullptr_t;
#else
    typedef decltype(nullptr) nullptr_t;
#endif
}
#  endif
#else
namespace BloombergLP {

namespace bsls {
                       // ===================
                       // class bsls::Nullptr
                       // ===================

struct Nullptr_Impl {
    // This implementation-private 'struct' provides an alias for a type that
    // can match a null pointer literal, but is not a pointer itself.  It
    // offers a limited emulation of the C++11 'std::nullptr_t' type.

  private:
    struct Nullptr_ProxyType { int dummy; }; // private class to supply a
                                             // unique pointer-to-member type.

  public:
    typedef int Nullptr_ProxyType::* Type;   // alias to an "unspecified" null
                                             // pointer type.
};

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

namespace bsl {

    typedef BloombergLP::bsls::Nullptr_Impl::Type nullptr_t;
        // Alias for a type that can match a null pointer literal, but is not a
        // pointer type itself.
}
#endif

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