blob: 35efaa96af2cc166147aee21100eeef78f8cf3b9 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FBL_HARD_INT_H_
#define FBL_HARD_INT_H_
#include <type_traits>
// HardInt is a a strongly-typed wrapper around integral types; HardInts
// do not implicitly convert even where the underlying integral type would.
// HardInt provides equality and comparison operators but does not provide
// arithmetic operators.
//
// HardInt is the same size as the underlying integral type.
// Example:
// DEFINE_HARD_INT(Celsius, uint64_t)
// DEFINE_HARD_INT(Fahrenheit, uint64_t)
// ...
// Celsius c1(40);
// Celsius c2(100);
// Fahrenheit f(451);
// c1 + 1; <-- Compile error
// static_assert(c1 == 1); <-- Compile error
// assert(c1 == c2); <-- Allowed
// static_assert(c1 != c2); <-- Allowed
// assert(c1.value() == 40); <-- Allowed
// c1 = c2; <-- Allowed
// f = c1; <-- Compile error
// Create a wrapper around |base_type| named |type_name|.
#define DEFINE_HARD_INT(type_name, base_type) \
struct type_name##_type_tag_ {}; \
using type_name = fbl::HardInt<type_name##_type_tag_, base_type>; \
\
static_assert(sizeof(type_name) == sizeof(base_type));
namespace fbl {
template <typename UniqueTagType, typename T>
class HardInt {
public:
constexpr HardInt() = default;
constexpr explicit HardInt(T value) : value_(value) {}
constexpr T value() const { return value_; }
constexpr bool operator==(const HardInt& other) const {
return value_ == other.value_;
}
constexpr bool operator<(const HardInt& other) const {
return value_ < other.value_;
}
private:
static_assert(std::is_integral<T>::value, "T must be an integral type.");
T value_;
};
} // namespace fbl
#endif // FBL_HARD_INT_H_