Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
util_intops Namespace Reference

Classes

class  StrongInt
 
class  StrongIntRange
 
class  StrongVector
 

Functions

template<typename StrongIntName , typename ValueType >
std::ostream & operator<< (std::ostream &os, StrongInt< StrongIntName, ValueType > arg)
 
template<typename Sink , typename... T>
void AbslStringify (Sink &sink, StrongInt< T... > arg)
 
 STRONG_INT_TYPE_ARITHMETIC_OP (+)
 
 STRONG_INT_TYPE_ARITHMETIC_OP (-)
 
STRONG_INT_TYPE_ARITHMETIC_OP * STRONG_INT_TYPE_ARITHMETIC_OP (/);STRONG_INT_TYPE_ARITHMETIC_OP(<<
 
 STRONG_INT_TYPE_ARITHMETIC_OP (> >)
 
 STRONG_INT_TYPE_ARITHMETIC_OP (%)
 
 STRONG_INT_TYPE_COMPARISON_OP (==)
 
 STRONG_INT_TYPE_COMPARISON_OP (!=)
 
 STRONG_INT_TYPE_COMPARISON_OP (<=)
 
 STRONG_INT_TYPE_COMPARISON_OP (>=)
 
template<typename IntType >
StrongIntRange< IntType > MakeStrongIntRange (IntType end)
 
template<typename IntType >
StrongIntRange< IntType > MakeStrongIntRange (IntType begin, IntType end)
 

Variables

class util_intops::StrongInt ABSL_ATTRIBUTE_PACKED
 

Detailed Description

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 is a simple template class mechanism for defining "logical" integer-like class types that support many of the same functionalities as native integer types, but which prevent assignment, construction, and other operations from other similar integer-like types. Essentially, the template class StrongInt<StrongIntName, ValueType> (where ValueType assumes valid scalar types such as int, uint, int32_t, etc) has the additional property that it cannot be assigned to or constructed from other StrongInts or native integer types of equal or implicitly convertible type.

The class is useful for preventing mingling of integer variables with different logical roles or units. Unfortunately, C++ provides relatively good type-safety for user-defined classes but not for integer types. It is essentially up to the user to use nice variable names and comments to prevent accidental mismatches, such as confusing a user-index with a group-index or a time-in-milliseconds with a time-in-seconds. The use of typedefs are limited in that regard as they do not enforce type-safety.

USAGE --------------------------------------------------------------------—

DEFINE_STRONG_INT_TYPE(StrongIntName, ValueType);
#define DEFINE_STRONG_INT_TYPE(int_type_name, value_type)
Definition strong_int.h:168

where: StrongIntName: is the desired (unique) name for the "logical" integer type ValueType: is one of the integral types as defined by std::is_integral (see <type_traits>).

DISALLOWED OPERATIONS / TYPE-SAFETY ENFORCEMENT --------------------------—

Consider these definitions and variable declarations: DEFINE_STRONG_INT_TYPE(GlobalDocID, int64_t); DEFINE_STRONG_INT_TYPE(LocalDocID, int64_t); GlobalDocID global; LocalDocID local;

The class StrongInt prevents:

1) Assignments of other StrongInts with different StrongIntNames.

global = local; <-- Fails to compile!
local = global; <-- Fails to compile!
trees with all degrees equal to

2) Explicit/implicit conversion from an StrongInt to another StrongInt.

LocalDocID l(global); <-- Fails to compile!
LocalDocID l = global; <-- Fails to compile!
void GetGlobalDoc(GlobalDocID global) { }
GetGlobalDoc(global); <-- Compiles fine, types match!
GetGlobalDoc(local); <-- Fails to compile!

3) Implicit conversion from an StrongInt to a native integer type.

void GetGlobalDoc(int64_t global) { ...
GetGlobalDoc(global); <-- Fails to compile!
GetGlobalDoc(local); <-- Fails to compile!
void GetLocalDoc(int32_t local) { ...
GetLocalDoc(global); <-- Fails to compile!
GetLocalDoc(local); <-- Fails to compile!

SUPPORTED OPERATIONS -----------------------------------------------------—

The following operators are supported: unary: ++ (both prefix and postfix), +, -, ! (logical not), ~ (one's complement); comparison: ==, !=, <, <=, >, >=; numerical: +, -, *, /; assignment: =, +=, -=, /=, *=; stream: <<. Each operator allows the same StrongIntName and the ValueType to be used on both left- and right-hand sides.

It also supports an accessor value() returning the stored value as ValueType, and a templatized accessor value<T>() method that serves as syntactic sugar for static_cast<T>(var.value()). These accessors are useful when assigning the stored value into protocol buffer fields and using it as printf args.

The class also defines a hash functor that allows the StrongInt to be used as key to hashable containers such as hash_map and hash_set.

We suggest using the StrongIntIndexedContainer wrapper around google3's FixedArray and STL vector (see int-type-indexed-container.h) if an StrongInt is intended to be used as an index into these containers. These wrappers are indexed in a type-safe manner using StrongInts to ensure type-safety.

NB: this implementation does not attempt to abide by or enforce dimensional analysis on these scalar types.

EXAMPLES -----------------------------------------------------------------—

DEFINE_STRONG_INT_TYPE(GlobalDocID, int64_t);
GlobalDocID global = 3;
std::cout << global; <-- Prints 3 to stdout.
for (GlobalDocID i(0); i < global; ++i) {
std::cout << i;
} <-- Print(ln)s 0 1 2 to stdout
DEFINE_STRONG_INT_TYPE(LocalDocID, int64_t);
LocalDocID local;
std::cout << local; <-- Prints 0 to stdout it
default
initializes the value to 0.
local = 5;
local *= 2;
LocalDocID l(local);
std::cout << l + local; <-- Prints 20 to stdout.
GenericSearchRequest request;
request.set_doc_id(global.value()); <-- Uses value() to extract the value
from the StrongInt class.
int64_t value

REMARKS ------------------------------------------------------------------—

The following bad usage is permissible although discouraged. Essentially, it involves using the value*() accessors to extract the native integer type out of the StrongInt class. Keep in mind that the primary reason for the StrongInt class is to prevent accidental mingling of similar logical integer types – and not type casting from one type to another.

DEFINE_STRONG_INT_TYPE(GlobalDocID, int64_t); DEFINE_STRONG_INT_TYPE(LocalDocID, int64_t); GlobalDocID global; LocalDocID local;

global = local.value(); <– Compiles fine.

void GetGlobalDoc(GlobalDocID global) { ... GetGlobalDoc(local.value()); <– Compiles fine.

void GetGlobalDoc(int64_t global) { ... GetGlobalDoc(local.value()); <– Compiles fine.

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. This file provides the StrongVector container that wraps around the STL vector. The wrapper restrict indexing to a pre-specified type-safe integer type or StrongInt (see util/intops/strong_int.h). It prevents accidental indexing by different "logical" integer-like types (e.g. another StrongInt) or native integer types. The wrapper is useful as C++ and the standard template library allows the user to mix "logical" integral indices that might have a different role.

The container can only be indexed by an instance of an StrongInt class, which can be declared as:

DEFINE_STRONG_INT_TYPE(type_name, value_type);

where type_name is the desired name for the "logical" integer-like type and the value_type is a supported native integer type such as int or uint64_t (see util/intops/strong_int.h for details).

The wrapper exposes all public methods of STL vector and behaves mostly as pass-through. The only methods modified to ensure type-safety are the operator [] and the at() methods.

EXAMPLES -----------------------------------------------------------------—

DEFINE_STRONG_INT_TYPE(PhysicalChildIndex, int32_t);
PhysicalChildIndex physical_index;
vec[physical_index] = ...; <-- index type match: compiles properly.
vec.at(physical_index) = ...; <-- index type match: compiles properly.
int32_t physical_index;
vec[physical_index] = ...; <-- fails to compile.
vec.at(physical_index) = ...; <-- fails to compile.
DEFINE_STRONG_INT_TYPE(LogicalChildIndex, int32_t);
LogicalChildIndex logical_index;
vec[logical_index] = ...; <-- fails to compile.
vec.at(logical_index) = ...; <-- fails to compile.
int index

NB: Iterator arithmetic bypasses strong typing for the index.

OVERFLOW BEHAVIOR

This class ONLY guards against growing the size beyond the range indexable by the index type in debug mode. In optimized mode the user can CHECK IsValidSize() when deemed important.

Function Documentation

◆ AbslStringify()

template<typename Sink , typename... T>
void util_intops::AbslStringify ( Sink & sink,
StrongInt< T... > arg )

Define AbslStringify, for absl::StrAppend, absl::StrCat, and absl::StrFormat.

When using StrongInt with absl::StrFormat, use the "%v" specifier.

int8_t/uint8_t are not supported by the "%v" specifier due to it being ambiguous whether an integer or character should be printed.

Definition at line 306 of file strong_int.h.

◆ MakeStrongIntRange() [1/2]

template<typename IntType >
StrongIntRange< IntType > util_intops::MakeStrongIntRange ( IntType begin,
IntType end )

Definition at line 443 of file strong_int.h.

◆ MakeStrongIntRange() [2/2]

template<typename IntType >
StrongIntRange< IntType > util_intops::MakeStrongIntRange ( IntType end)

Definition at line 438 of file strong_int.h.

◆ operator<<()

template<typename StrongIntName , typename ValueType >
std::ostream & util_intops::operator<< ( std::ostream & os,
StrongInt< StrongIntName, ValueType > arg )

– NON-MEMBER STREAM OPERATORS -------------------------------------------— We provide the << operator, primarily for logging purposes. Currently, there seems to be no need for an >> operator.

Definition at line 297 of file strong_int.h.

◆ STRONG_INT_TYPE_ARITHMETIC_OP() [1/5]

util_intops::STRONG_INT_TYPE_ARITHMETIC_OP ( % )

◆ STRONG_INT_TYPE_ARITHMETIC_OP() [2/5]

util_intops::STRONG_INT_TYPE_ARITHMETIC_OP ( + )

◆ STRONG_INT_TYPE_ARITHMETIC_OP() [3/5]

util_intops::STRONG_INT_TYPE_ARITHMETIC_OP ( - )

◆ STRONG_INT_TYPE_ARITHMETIC_OP() [4/5]

STRONG_INT_TYPE_ARITHMETIC_OP * util_intops::STRONG_INT_TYPE_ARITHMETIC_OP ( / )

◆ STRONG_INT_TYPE_ARITHMETIC_OP() [5/5]

util_intops::STRONG_INT_TYPE_ARITHMETIC_OP ( )

◆ STRONG_INT_TYPE_COMPARISON_OP() [1/4]

util_intops::STRONG_INT_TYPE_COMPARISON_OP ( ! )

◆ STRONG_INT_TYPE_COMPARISON_OP() [2/4]

util_intops::STRONG_INT_TYPE_COMPARISON_OP ( <= )

◆ STRONG_INT_TYPE_COMPARISON_OP() [3/4]

util_intops::STRONG_INT_TYPE_COMPARISON_OP ( )

◆ STRONG_INT_TYPE_COMPARISON_OP() [4/4]

util_intops::STRONG_INT_TYPE_COMPARISON_OP ( >= )

Variable Documentation

◆ ABSL_ATTRIBUTE_PACKED

class util_intops::StrongInt util_intops::ABSL_ATTRIBUTE_PACKED