text: // Copyright 2013 Google Inc. All Rights Reserved.
  //
  // 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.
  
  // Various Google-specific macros.
  
  #ifndef SLING_BASE_MACROS_H_
  #define SLING_BASE_MACROS_H_
  
  #include "sling/base/port.h"
  
  namespace sling {
  
  // Put this in the declarations for a class to be uncopyable.
  #define DISALLOW_COPY(TypeName) \
    TypeName(const TypeName&) = delete
  
  // Put this in the declarations for a class to be unassignable.
  #define DISALLOW_ASSIGN(TypeName) \
    void operator=(const TypeName&) = delete
  
  // A macro to disallow the copy constructor and operator= functions
  // This should be used in the private: declarations for a class
  #define DISALLOW_COPY_AND_ASSIGN(TypeName) \
    TypeName(const TypeName&);               \
    void operator=(const TypeName&)
  
  // A macro to disallow all the implicit constructors, namely the
  // default constructor, copy constructor and operator= functions.
  //
  // This should be used in the private: declarations for a class
  // that wants to prevent anyone from instantiating it. This is
  // especially useful for classes containing only static methods.
  #define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
    TypeName() = delete;                           \
    DISALLOW_COPY_AND_ASSIGN(TypeName)
  
  // A macro to disallow the copy constructor and operator= functions
  // This should be used in the private: declarations for a class
  //
  // For disallowing only assign or copy, write the code directly, but declare
  // the intent in a comment, for example:
  // void operator=(const TypeName&);  // DISALLOW_ASSIGN
  // Note, that most uses of DISALLOW_ASSIGN and DISALLOW_COPY are broken
  // semantically, one should either use disallow both or neither. Try to
  // avoid these in new code.
  #define DISALLOW_COPY_AND_ASSIGN(TypeName) \
    TypeName(const TypeName&);               \
    void operator=(const TypeName&)
  
  // The arraysize(arr) macro returns the # of elements in an array arr.
  // The expression is a compile-time constant, and therefore can be
  // used in defining new arrays, for example.  If you use arraysize on
  // a pointer by mistake, you will get a compile-time error.
  //
  // One caveat is that, for C++03, arraysize() doesn't accept any array of
  // an anonymous type or a type defined inside a function.  In these rare
  // cases, you have to use the unsafe ARRAYSIZE() macro below.  This is
  // due to a limitation in C++03's template system.  The limitation has
  // been removed in C++11.
  
  // This template function declaration is used in defining arraysize.
  // Note that the function doesn't need an implementation, as we only
  // use its type.
  template <typename T, size_t N>
  char (&ArraySizeHelper(T (&array)[N]))[N];
  
  // That gcc wants both of these prototypes seems mysterious. VC, for
  // its part, can't decide which to use (another mystery). Matching of
  // template overloads: the final frontier.
  #ifndef _MSC_VER
  template <typename T, size_t N>
  char (&ArraySizeHelper(const T (&array)[N]))[N];
  #endif
  
  #define arraysize(array) (sizeof(ArraySizeHelper(array)))
  
  // ARRAYSIZE performs essentially the same calculation as arraysize,
  // but can be used on anonymous types or types defined inside
  // functions.  It's less safe than arraysize as it accepts some
  // (although not all) pointers.  Therefore, you should use arraysize
  // whenever possible.
  //
  // The expression ARRAYSIZE(a) is a compile-time constant of type
  // size_t.
  //
  // ARRAYSIZE catches a few type errors.  If you see a compiler error
  //
  //   "warning: division by zero in ..."
  //
  // when using ARRAYSIZE, you are (wrongfully) giving it a pointer.
  // You should only use ARRAYSIZE on statically allocated arrays.
  //
  // The following comments are on the implementation details, and can
  // be ignored by the users.
  //
  // ARRAYSIZE(arr) works by inspecting sizeof(arr) (the # of bytes in
  // the array) and sizeof(*(arr)) (the # of bytes in one array
  // element).  If the former is divisible by the latter, perhaps arr is
  // indeed an array, in which case the division result is the # of
  // elements in the array.  Otherwise, arr cannot possibly be an array,
  // and we generate a compiler error to prevent the code from
  // compiling.
  //
  // Since the size of bool is implementation-defined, we need to cast
  // !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final
  // result has type size_t.
  //
  // This macro is not perfect as it wrongfully accepts certain
  // pointers, namely where the pointer size is divisible by the pointee
  // size.  For code that goes through a 32-bit compiler, where a pointer
  // is 4 bytes, this means all pointers to a type whose size is 3 or
  // greater than 4 will be (righteously) rejected.
  //
  // Starting with Visual C++ 2005, WinNT.h includes ARRAYSIZE.
  #if !defined(_MSC_VER) || (defined(_MSC_VER) && _MSC_VER < 1400)
  #define ARRAYSIZE(a) \
    ((sizeof(a) / sizeof(*(a))) / \
     static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
  #endif
  
  // The FALLTHROUGH_INTENDED macro can be used to annotate implicit fall-through
  // between switch labels:
  //  switch (x) {
  //    case 40:
  //    case 41:
  //      if (truth_is_out_there) {
  //        ++x;
  //        FALLTHROUGH_INTENDED;  // Use instead of/along with annotations in
  //                               // comments.
  //      } else {
  //        return x;
  //      }
  //    case 42:
  //      ...
  //
  //  As shown in the example above, the FALLTHROUGH_INTENDED macro should be
  //  followed by a semicolon. It is designed to mimic control-flow statements
  //  like 'break;', so it can be placed in most places where 'break;' can, but
  //  only if there are no statements on the execution path between it and the
  //  next switch label.
  //
  //  When compiled with clang in C++11 mode, the FALLTHROUGH_INTENDED macro is
  //  expanded to [[clang::fallthrough]] attribute, which is analysed when
  //  performing switch labels fall-through diagnostic ('-Wimplicit-fallthrough').
  //  See clang documentation on language extensions for details:
  //  http://clang.llvm.org/docs/LanguageExtensions.html#clang__fallthrough
  //
  //  When used with unsupported compilers, the FALLTHROUGH_INTENDED macro has no
  //  effect on diagnostics.
  //
  //  In either case this macro has no effect on runtime behavior and performance
  //  of code.
  #if defined(__clang__) && defined(LANG_CXX11) && defined(__has_warning)
  #if __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough")
  #define FALLTHROUGH_INTENDED [[clang::fallthrough]]  // NOLINT
  #endif
  #endif
  
  #ifndef FALLTHROUGH_INTENDED
  #define FALLTHROUGH_INTENDED do { } while (0)
  #endif
  
  }  // namespace sling
  
  #endif  // SLING_BASE_MACROS_H_
  