chromium/base/scoped_generic.h

// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef BASE_SCOPED_GENERIC_H_
#define BASE_SCOPED_GENERIC_H_

#include <stdlib.h>

#include <concepts>
#include <type_traits>

#include "base/check.h"
#include "base/memory/raw_ptr.h"

namespace base {

// This class acts like unique_ptr with a custom deleter (although is slightly
// less fancy in some of the more escoteric respects) except that it keeps a
// copy of the object rather than a pointer, and we require that the contained
// object has some kind of "invalid" value.
//
// Defining a scoper based on this class allows you to get a scoper for
// non-pointer types without having to write custom code for set, reset, and
// move, etc. and get almost identical semantics that people are used to from
// unique_ptr.
//
// It is intended that you will typedef this class with an appropriate deleter
// to implement clean up tasks for objects that act like pointers from a
// resource management standpoint but aren't, such as file descriptors and
// various types of operating system handles. Using unique_ptr for these
// things requires that you keep a pointer to the handle valid for the lifetime
// of the scoper (which is easy to mess up).
//
// For an object to be able to be put into a ScopedGeneric, it must support
// standard copyable semantics and have a specific "invalid" value. The traits
// must define a free function and also the invalid value to assign for
// default-constructed and released objects.
//
//   struct FooScopedTraits {
//     // It's assumed that this is a fast inline function with little-to-no
//     // penalty for duplicate calls. This must be a static function even
//     // for stateful traits.
//     static int InvalidValue() {
//       return 0;
//     }
//
//     // This free function will not be called if f == InvalidValue()!
//     static void Free(int f) {
//       ::FreeFoo(f);
//     }
//   };
//
//   using ScopedFoo = ScopedGeneric<int, FooScopedTraits>;
//
// A Traits type may choose to track ownership of objects in parallel with
// ScopedGeneric. To do so, it must implement the Acquire and Release methods,
// which will be called by ScopedGeneric during ownership transfers and extend
// the ScopedGenericOwnershipTracking tag type.
//
//   struct BarScopedTraits : public ScopedGenericOwnershipTracking {
//     using ScopedGenericType = ScopedGeneric<int, BarScopedTraits>;
//     static int InvalidValue() {
//       return 0;
//     }
//
//     static void Free(int b) {
//       ::FreeBar(b);
//     }
//
//     static void Acquire(const ScopedGenericType& owner, int b) {
//       ::TrackAcquisition(b, owner);
//     }
//
//     static void Release(const ScopedGenericType& owner, int b) {
//       ::TrackRelease(b, owner);
//     }
//   };
//
//   using ScopedBar = ScopedGeneric<int, BarScopedTraits>;
struct ScopedGenericOwnershipTracking {};

template<typename T, typename Traits>
class ScopedGeneric {};

template<class T, class Traits>
void swap(const ScopedGeneric<T, Traits>& a,
          const ScopedGeneric<T, Traits>& b) {}

template<class T, class Traits>
bool operator==(const T& value, const ScopedGeneric<T, Traits>& scoped) {}

template<class T, class Traits>
bool operator!=(const T& value, const ScopedGeneric<T, Traits>& scoped) {}

}  // namespace base

#endif  // BASE_SCOPED_GENERIC_H_