Provide an value-semantic type to represent type_info
objects.
More...
Detailed Description
- Outline
-
-
- Purpose:
- Provide an value-semantic type to represent
type_info
objects.
-
- Classes:
-
- Canonical Header:
- bsl_typeindex.h
- See also:
- bsl_typeinfo
-
- Description:
- This component defines an in-core value-semantic class,
bsl::type_index
, capable of representing a handle to a std::type_info
object that supports all the operations needed to serve as a key type in an associative or unordered container.
- This implementation of
type_index
satisfies the contracts for the native std::type_index
specified in the ISO standard, including a specialization for the native standard library std::hash
. It further provides an overload for hashAppend
to support the BDE hashing framework, and therefor idiomatic usage with bsl::hash
. In general, the recommended best practice is that users of bsl
containers should use the bsl::type_index
class, while users of std
containers should use the std::type_index
class.
-
- Usage:
- This section illustrates intended use of this component.
-
- Example 1: Basic Use of bsl::type_index:
- Assume you are implementing a graphics library, and need to represent a variety of shapes. You might have a simple hierarchy, such as:
+-----------------------------------------------------------------+
| |
| .---------. |
| ( Shape ) |
| `---------' |
| ^ ^ ^ |
| / | \ |
| / | \ |
| / | \ |
| ,------. ,--------. ,-------. |
| ( Circle ) ( Triangle ) ( Polygon ) |
| `------' `--------' `-------' |
| |
+-----------------------------------------------------------------+
In order to manage the creation of objects in our hierarchy, we might deploy the Abstract Factory pattern: https://en.wikipedia.org/wiki/Abstract_factory_pattern using objects of type bsl::function<shared_ptr<Shape> >
as factories.
- First, we define our basic class hierarchy.
class Shape {
public:
virtual ~Shape() = 0;
};
Then, we create a utility class containing a registry of factory functions indexed by their corresponding std::type_info
, using bsl::type_index
to provide the value-semantic wrapper needed for the key used in the container. This registry will enable us to abstract away different constructors of the concrete object types. Now, we can implement the register and make functions, using the standard typeid
operator to create the key values as needed. template <class SHAPE_TYPE>
bsl::shared_ptr<Shape> ShapeUtil::make(int x, int y) {
AbstractFactory::iterator it = s_registry.find(typeid(SHAPE_TYPE));
if (s_registry.end() == it) {
return 0;
}
return it->second(x, y);
}
template <class SHAPE_TYPE, class FACTORY>
bool ShapeUtil::registerFactory(FACTORY factory) {
return s_registry.emplace(typeid(SHAPE_TYPE), factory).second;
}
Next, we provide several concrete implementations of our Shape
class, to demonstrate use of this hierarchy. class Circle : public Shape {
public:
Circle(int x, int y, int radius);
~Circle();
};
class Triangle : public Shape {
public:
Triangle(int x1, int y1, int x2, int y2, int x3, int y3);
~Triangle();
};
class Polygon : public Shape {
public:
template <class ITERATOR>
Polygon(ITERATOR firstPoint, ITERATOR endPoint);
~Polygon();
};
Then, we provide some simple factory functions to create some shapes at the specified coordinates. Finally, we can exercise the whole system in a simple test driver. Note that as we do not register a factory function for the Polygon
class, the attempt to create a Polygon
will fail. int main()
{
bslma::TestAllocator ta("Usage example default allocator");
bslma::DefaultAllocatorGuard guard(&ta);
bool registeredCircle = ShapeUtil::registerFactory<Circle>(makeCircle);
assert(registeredCircle);
bool registeredTriangle =
ShapeUtil::registerFactory<Triangle>(makeTriangle);
assert(registeredTriangle);
bsl::shared_ptr<Shape> example = ShapeUtil::make<Circle>(10, 10);
assert(0 != bsl::dynamic_pointer_cast<Circle>(example));
example = ShapeUtil::make<Triangle>(10, 10);
assert(0 != bsl::dynamic_pointer_cast<Triangle>(example));
example = ShapeUtil::make<Polygon>(10, 10);
assert(0 == example);
return 0;
}
Function Documentation
bsl::type_index::type_index |
( |
const std::type_info & |
target |
) |
[inherited] |
IMPLICIT: Create a type_index
object having a reference to the type designated by the specified target
.
bsl::type_index::type_index |
( |
const type_index & |
original |
) |
[inherited] |
Create a type_index
object having the value of the specified original
date. Note that this trivial function is implicitly supplied by the compiler.
bsl::type_index::~type_index |
( |
|
) |
[inherited] |
Destroy this object. Note that this trivial function is implicitly supplied by the compiler.
type_index& bsl::type_index::operator= |
( |
const type_index & |
rhs |
) |
[inherited] |
Assign to this object the value of the specified rhs
type-index, and return a reference providing modifiable access to this object. Note that this trivial function is implicitly supplied by the compiler.
bool bsl::type_index::operator== |
( |
const type_index & |
other |
) |
const [inherited] |
Return true
if this and the specified other
objects have the same value, and false
otherwise. Two type_index
objects have the same value if they refer to the same type.
bool bsl::type_index::operator!= |
( |
const type_index & |
other |
) |
const [inherited] |
Return true
if this and the specified other
objects do not have the same value, and false
otherwise. Two type_index
objects do not have the same value if they refer to different types.
bool bsl::type_index::operator< |
( |
const type_index & |
other |
) |
const [inherited] |
Return true
if the type referenced by this object is ordered before the type referenced by the specified other
object in the implementation defined ordering of types defined by the compiler, and false
otherwise.
bool bsl::type_index::operator<= |
( |
const type_index & |
other |
) |
const [inherited] |
Return true
if the type referenced by this object is the same as the type referenced by the specified other
object, or ordered before the type referenced by the other
in the implementation defined ordering of types defined by the compiler, and false
otherwise.
bool bsl::type_index::operator> |
( |
const type_index & |
other |
) |
const [inherited] |
Return true
if the type referenced by this object is ordered after the type referenced by the specified other
object in the implementation defined ordering of types defined by the compiler, and false
otherwise.
bool bsl::type_index::operator>= |
( |
const type_index & |
other |
) |
const [inherited] |
Return true
if the type referenced by this object is the same as the type referenced by the specified other
object, or ordered after the type referenced by the other
in the implementation defined ordering of types defined by the compiler, and false
otherwise.
size_t bsl::type_index::hash_code |
( |
|
) |
const [inherited] |
Return the hash_code
of the referenced type_info
object.
const char* bsl::type_index::name |
( |
|
) |
const [inherited] |
Return the name
of the referenced type_info
object.
template<class HASHALG >
void bsl::hashAppend |
( |
HASHALG & |
hashAlg, |
|
|
const type_index & |
object | |
|
) |
| | |
Pass the specified object
to the specified hashAlg
. This function integrates with the bslh
modular hashing system and effectively provides a bsl::hash
specialization for type_index
.