blob: 5d4ae41e787562a3a5d3dfe1aedf046efc301f83 [file] [log] [blame]
// Copyright 2015 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.
#ifndef COBALT_BASE_TYPE_ID_H_
#define COBALT_BASE_TYPE_ID_H_
#include "base/hash_tables.h"
// This file introduces the template function GetTypeId<T>() as well as the
// class TypeId. GetTypeId<T>() will return a TypeId object that is unique
// to the type T passed as the template parameter. This can be used to
// implement run-time type identification on certain types without actually
// enabling RTTI on the compiler.
// Some of this code is copied from gtest-internal.h.
namespace base {
namespace internal {
template <typename T>
class TypeIdHelper {
public:
// dummy_ must not have a const type. Otherwise an overly eager
// compiler (e.g. MSVC 7.1 & 8.0) may try to merge
// TypeIdHelper<T>::dummy_ for different Ts as an "optimization".
static bool dummy_;
};
// The compiler is required to allocate a different
// TypeIdHelper<T>::dummy_ variable for each T used to instantiate
// the template. Therefore, the address of dummy_ is guaranteed to
// be unique.
template <typename T>
bool TypeIdHelper<T>::dummy_ = false;
} // namespace internal
class TypeId {
public:
bool operator==(const TypeId& other) const { return value_ == other.value_; }
bool operator!=(const TypeId& other) const { return !(*this == other); }
bool operator<(const TypeId& other) const { return value_ < other.value_; }
bool operator<=(const TypeId& other) const { return value_ <= other.value_; }
bool operator>(const TypeId& other) const { return value_ > other.value_; }
bool operator>=(const TypeId& other) const { return value_ >= other.value_; }
private:
explicit TypeId(intptr_t value) : value_(value) {}
intptr_t value_;
template <typename T> friend TypeId GetTypeId();
#if defined(BASE_HASH_USE_HASH_STRUCT)
friend struct BASE_HASH_NAMESPACE::hash<TypeId>;
#else
template <typename T, typename Predicate>
friend class BASE_HASH_NAMESPACE::hash_compare;
#endif
};
// GetTypeId<T>() returns the ID of type T. Different values will be
// returned for different types. Calling the function twice with the
// same type argument is guaranteed to return the same ID.
template <typename T>
TypeId GetTypeId() {
return
TypeId(reinterpret_cast<intptr_t>(&(internal::TypeIdHelper<T>::dummy_)));
}
} // namespace base
// Make TypeId usable as key in base::hash_map.
namespace BASE_HASH_NAMESPACE {
//
// GCC-flavored hash functor.
//
#if defined(BASE_HASH_USE_HASH_STRUCT)
// Forward declaration in case <hash_fun.h> is not #include'd.
template <typename Key>
struct hash;
template <>
struct hash<base::TypeId> {
size_t operator()(const base::TypeId& key) const {
return base_hash(key.value_);
}
hash<intptr_t> base_hash;
};
//
// Dinkumware-flavored hash functor.
//
#else
// Forward declaration in case <xhash> is not #include'd.
template <typename Key, typename Predicate>
class hash_compare;
template <typename Predicate>
class hash_compare<base::TypeId, Predicate> {
public:
typedef hash_compare<intptr_t> BaseHashCompare;
enum {
bucket_size = BaseHashCompare::bucket_size,
#if !defined(COMPILER_MSVC)
min_buckets = BaseHashCompare::min_buckets,
#endif
};
hash_compare() {}
size_t operator()(const base::TypeId& key) const {
return base_hash_compare_(key.value_);
}
bool operator()(const base::TypeId& lhs,
const base::TypeId& rhs) const {
return base_hash_compare_(lhs.value_, rhs.value_);
}
private:
BaseHashCompare base_hash_compare_;
};
#endif
} // namespace BASE_HASH_NAMESPACE
#endif // COBALT_BASE_TYPE_ID_H_