// Copyright 2019 The MediaPipe Authors. // // 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. // StrongInt<T> is a simple template class mechanism for defining "logical" // integer-like class types that support almost all of the same functionality // as native integer types, but which prevents assignment, construction, and // other operations from other integer-like types. In other words, you cannot // assign from raw integer types or other StrongInt<> types, nor can you do // most arithmetic or logical operations. This provides a simple form of // dimensionality in that you can add two instances of StrongInt<T>, producing // a StrongInt<T>, but you can not add a StrongInt<T> and a raw T nor can you // add a StrongInt<T> and a StrongInt<U>. Details on supported operations are // below. // // In addition to type strength, StrongInt provides a way to inject (optional) // validation of the various operations. This allows you to define StrongInt // types that check for overflow conditions and react in standard or custom // ways. // // A StrongInt<T> with a NullStrongIntValidator should compile away to a raw T // in optimized mode. What this means is that the generated assembly for: // // int64_t foo = 123; // int64_t bar = 456; // int64_t baz = foo + bar; // constexpr int64_t fubar = 789; // // ...should be identical to the generated assembly for: // // DEFINE_STRONG_INT_TYPE(MyStrongInt, int64_t); // MyStrongInt foo(123); // MyStrongInt bar(456); // MyStrongInt baz = foo + bar; // constexpr MyStrongInt fubar(789); // // Since the methods are all inline and non-virtual and the class has just // one data member, the compiler can erase the StrongInt class entirely in its // code-generation phase. This also means that you can pass StrongInt<T> // around by value just as you would a raw T. // // It is important to note that StrongInt does NOT generate compile time // warnings or errors for overflows on implicit constant conversions. // // Usage: // StrongInt<TagType, NativeType, ValidatorType = NullStrongIntValidator> // // Creates a new StrongInt instance directly. // // TagType: The unique type which discriminates this StrongInt<T> from // other StrongInt<U> types. // NativeType: The primitive integral type this StrongInt will hold, as // defined by std::is_integral (see <type_traits>). // ValidatorType: The type of validation used by this StrongInt type. A // few pre-built validator types are provided here, but the caller can // define any custom validator they desire. // // Supported operations: // StrongInt<T> = StrongInt<T> // !StrongInt<T> => bool // ~StrongInt<T> => StrongInt<T> // -StrongInt<T> => StrongInt<T> // +StrongInt<T> => StrongInt<T> // ++StrongInt<T> => StrongInt<T> // StrongInt<T>++ => StrongInt<T> // --StrongInt<T> => StrongInt<T> // StrongInt<T>-- => StrongInt<T> // StrongInt<T> + StrongInt<T> => StrongInt<T> // StrongInt<T> - StrongInt<T> => StrongInt<T> // StrongInt<T> * (numeric type) => StrongInt<T> // StrongInt<T> / (numeric type) => StrongInt<T> // StrongInt<T> % (numeric type) => StrongInt<T> // StrongInt<T> << (numeric type) => StrongInt<T> // StrongInt<T> >> (numeric type) => StrongInt<T> // StrongInt<T> & StrongInt<T> => StrongInt<T> // StrongInt<T> | StrongInt<T> => StrongInt<T> // StrongInt<T> ^ StrongInt<T> => StrongInt<T> // // For binary operations, the equivalent op-equal (eg += vs. +) operations are // also supported. Other operator combinations should cause compile-time // errors. // // Validators: // NullStrongIntValidator: Do no validation. This should be entirely // optimized away by the compiler. #ifndef MEDIAPIPE_DEPS_STRONG_INT_H_ #define MEDIAPIPE_DEPS_STRONG_INT_H_ #include <cstdint> #include <iosfwd> #include <limits> #include <ostream> #include <type_traits> #include "absl/base/macros.h" #include "absl/log/absl_log.h" #include "mediapipe/framework/port/port.h" namespace mediapipe { intops // namespace intops } // namespace mediapipe #endif // MEDIAPIPE_DEPS_STRONG_INT_H_