Quick Links: |
Provide type category tags and a tag selection meta-function. More...
Classes | |
struct | bdlat_TypeCategoryDeclareDynamic< TYPE > |
struct | bdlat_TypeCategory |
struct | bdlat_TypeCategoryUtil |
Namespaces | |
namespace | bdlat_TypeCategoryFunctions |
bdlat_TypeCategory::Array | tag for array types |
bdlat_TypeCategory::Choice | tag for choice types |
bdlat_TypeCategory::CustomizedType | tag for customized types |
bdlat_TypeCategory::DynamicType | tag for customized types |
bdlat_TypeCategory::Enumeration | tag for enumeration types |
bdlat_TypeCategory::NullableValue | tag for nullable types |
bdlat_TypeCategory::Sequence | tag for sequence types |
bdlat_TypeCategory::Simple | tag for simple types |
bdlat_TypeCategory::Select | meta-function for selecting tag |
bdlat_TypeCategoryDeclareDynamic | trait to declare dynamic type |
bdlat_TypeCategoryFunctions | overloadable type category functions |
bdlat_TypeCategoryUtil | type category utility |
bdlat
class categories. This facilities consist of: bdlat_TypeCategory::Array
, bdlat_TypeCategory::Choice
) and enumerators (e.g., bdlat_TypeCategory::e_ARRAY_CATEGORY
bdlat_TypeCategory::e_CHOICE_CATEGORY
) that can be used to describe how a user-defined type participates in the bdlat
type framework and a meta-function, bdlat_TypeCategory::Select
, that can be used to access that information for a parameterized TYPE
. Category Tag Assigned To ------------ ----------- Array types that expose "array" behavior through the 'bdlat_ArrayFunctions' 'namespace'. Choice types that expose "choice" behavior through the 'bdlat_ChoiceFunctions' 'namespace'. CustomizedType types that expose "customized type" behavior through the 'bdlat_CustomizedTypeFunctions' 'namespace'. DynamicType types that can select a category at runtime Enumeration types that expose "enumeration" behavior through the 'bdlat_EnumFunctions' 'namespace'. NullableValue types that expose "nullable" behavior through the 'bdlat_NullableValueFunctions' 'namespace'. Sequence types that expose "sequence" behavior through the 'bdlat_SequenceFunctions' 'namespace'. Simple all other types (i.e., scalars)
DynamicType
category also belong to one or more other categories. Otherwise, a type may only belong to one category. bdlat_TypeCategory::Select
, used to detect at compile time the type category of a template parameter TYPE
, which must be a bdlat
-compatible type. This meta-function defines two (nested) names: Type
: The category tag type for the template parameter TYPE
. e_SELECTION
: The enumerator for the category of the template parameter TYPE
. TYPE
has set the type trait corresponding to its bdlat
type category. For example, if TYPE
is a bdlat
"array" type then: and if TYPE
is a bdlat
"choice" type then: Additionally, TYPE
must also meet the other requirements (e.g., defined functions, defined types) of its bdlat
type category. TYPE
, it is assumed to be in the Simple
(scalar) category. If more than one of these traits have been set of TYPE
, TYPE
is classified as Dynamic
.
bdlat_TypeCategoryDeclareDynamic
trait. struct
, bdlat_TypeCategoryUtil
, that provides two function templates: manipulateByCategory
and accessByCategory
that invoke a MANIPULATOR
or ACCESSOR
functor, respectively. Both of these functor types provide an overload for each of the bdlat
type categories (see MANIPULATOR
Functors and ACCESSOR
Functors). These utility functions determine the bdlat
type category (see bdlat_TypeCategoryFunctions::select
) of a given object and then invoke the corresponding overload of the given functor. MANIPULATOR
functor must be invocable by one or more of these seven overloads: int MANIPULATOR(TYPE *object, bdlat_TypeCategory::Array category); int MANIPULATOR(TYPE *object, bdlat_TypeCategory::Choice category); int MANIPULATOR(TYPE *object, bdlat_TypeCategory::CustomizedType category); int MANIPULATOR(TYPE *object, bdlat_TypeCategory::Enumeration category); int MANIPULATOR(TYPE *object, bdlat_TypeCategory::NullableValue category); int MANIPULATOR(TYPE *object, bdlat_TypeCategory::Sequence category); int MANIPULATOR(TYPE *object, bdlat_TypeCategory::Simple category); // Modify the specified 'object' that matches the specified 'category'. // Return 0 on success and a non-zero value otherwise. On failure, // 'object' is left in a valid but unspecified state. The behavior is // undefined unless the type category of 'object' matches 'category'.
bdlat
type categories (i.e., all except for the "dynamic" category). bslmf::Nil
(required for compilation): int MANIPULATOR(TYPE *object, bslmf::Nil); // Modify the specified 'object'. Return 0 on success and a non-zero // value otherwise. On failure, 'object' is left in a valid but // unspecified state. The behavior is undefined if 'TYPE' is 'bdlat' // compatible (i.e., belongs in one or more of the seven 'bdlat' // categories). Note that 'bdlat' compatible types are expected to be // dispatched to one of the seven overloads declared above.
ACCESSOR
functor must invocable by one or more of these seven overloads: int ACCESSOR(const TYPE& object, bdlat_TypeCategory::Array cat); int ACCESSOR(const TYPE& object, bdlat_TypeCategory::Choice cat); int ACCESSOR(const TYPE& object, bdlat_TypeCategory::CustomizedType cat); int ACCESSOR(const TYPE& object, bdlat_TypeCategory::Enumeration cat); int ACCESSOR(const TYPE& object, bdlat_TypeCategory::NullableValue cat); int ACCESSOR(const TYPE& object, bdlat_TypeCategory::Sequence cat); int ACCESSOR(const TYPE& object, bdlat_TypeCategory::Simple cat); // Access the specified 'object' that matches the specified 'cat' // (category). Return 0 on success and a non-zero value otherwise. // The behavior is undefined unless the type category of 'object' // matches 'cat' (category). Note that, in typical use, invocation of // this functor object changes its state based on the state of // 'object'.
bdlat
type categories (i.e., all except for the "dyanamic" category). bslmf::Nil
(required for compilation): int ACCESSOR(const TYPE& object, bslmf::Nil); // Access the specified 'object'. Return 0 on success and a non-zero // value otherwise. The behavior is undefined if 'TYPE' is 'bdlat' // compatible (i.e., belongs in one or more of the seven 'bdlat' // categories). Note that 'bdlat' compatible types are expected to be // dispatched to one of the seven overloads declared above.
bdlat_TypeCategoryFunctions
defines a suite of function templates for working with types that conform to one or more of the bdlat
type categories. For each of the seven type categories there are a pair of function templates: one to "manipulate" and one to "access" objects of (template parameter) TYPE
. For example, for bdlat
"array" types there are function templates: bdlat_TypeCategoryFunctions::manipulateArray
and bdlat_TypeCategoryFunctions::accessArray
. bdlat_TypeCategoryFunctions::select
, that reports at runtime the type category of a specified object. MANIPULATOR
Functors and ACCESSOR
Functors for the requirements on those functors. bdlat
type category of the type. For example, if the type being plugged into the framework is a bdlat
"array" type, then overloads for bdlat_typeCategoryManipulateArray
and bdlat_typeCategoryAccessArray
are required. If the type being plugged into the infrastructure belongs to more than one bdlat
type category, the "manipulate" and "accessor" function templates for each of those type categories is required. bdlat_typeCategorySelect
function. YOUR_TYPE
is not a template argument and should be replaced with the name of the type being plugged into the framework. // MANIPULATORS template <class MANIPULATOR> int bdlat_typeCategoryManipulateArray(YOUR_TYPE *object, MANIPULATOR& manipulator); // Return the result of invoking the specified 'manipulator' with the // specified 'object' (1st argument) and a 'bdlat_TypeCategory::Array' // tag object (2nd argument). If 'object' is not a 'bdlat' "array" // type, pass a 'bslmf::Nil' tag object as the second argument. See // {'MANIPULATOR' Functors} for the requirements on 'manipulator'. template <class MANIPULATOR> int bdlat_typeCategoryManipulateChoice(YOUR_TYPE *object, MANIPULATOR& manipulator); // Return the result of invoking the specified 'manipulator' with the // specified 'object' (1st argument) and a 'bdlat_TypeCategory::Choice' // tag object (2nd argument). If 'object' is not a 'bdlat' "choice" // type, pass a 'bslmf::Nil' tag object as the second argument. See // {'MANIPULATOR' Functors} for the requirements on 'manipulator'. template <class MANIPULATOR> int bdlat_typeCategoryManipulateCustomizedType(YOUR_TYPE *object, MANIPULATOR& manipulator); // Return the result of invoking the specified 'manipulator' with the // specified 'object' (1st argument) and a // 'bdlat_TypeCategory::CustomizedType' tag object (2nd argument). If // 'object' is not a 'bdlat' "customized type" type, pass a // 'bslmf::Nil' tag object as the second argument. See {'MANIPULATOR' // Functors} for the requirements on 'manipulator'. template <class MANIPULATOR> int bdlat_typeCategoryManipulateEnumeration(YOUR_TYPE *object, MANIPULATOR& manipulator); // Return the result of invoking the specified 'manipulator' with the // specified 'object' (1st argument) and a // 'bdlat_TypeCategory::Enumeration' tag object (2nd argument). If // 'object' is not a 'bdlat' "enumeration" type, pass a 'bslmf::Nil' // tag object as the second argument. See {'MANIPULATOR' Functors} for // the requirements on 'manipulator'. template <class MANIPULATOR> int bdlat_typeCategoryManipulateNullableValue(YOUR_TYPE *object, MANIPULATOR& manipulator); // Return the result of invoking the specified 'manipulator' with the // specified 'object' (1st argument) and a // 'bdlat_TypeCategory::NullableValue' tag object (2nd argument). If // 'object' is not a 'bdlat' "nullable value" type, pass a 'bslmf::Nil' // tag object as the second argument. See {'MANIPULATOR' Functors} for // the requirements on 'manipulator'. template <class MANIPULATOR> int bdlat_typeCategoryManipulateSequence(YOUR_TYPE *object, MANIPULATOR& manipulator); // Return the result of invoking the specified 'manipulator' with the // specified 'object' (1st argument) and a // 'bdlat_TypeCategory::Sequence' tag object (2nd argument). If // 'object' is not a 'bdlat' "sequence" type, pass a 'bslmf::Nil' tag // object as the second argument. See {'MANIPULATOR' Functors} for the // requirements on 'manipulator'. template <class MANIPULATOR> int bdlat_typeCategoryManipulateSimple(YOUR_TYPE *object, MANIPULATOR& manipulator); // Return the result of invoking the specified 'manipulator' with the // specified 'object' (1st argument) and a 'bdlat_TypeCategory::Simple' // tag object (2nd argument). If 'object' is not a 'bdlat' "simple" // type, pass a 'bslmf::Nil' tag object as the second argument. See // {'MANIPULATOR' Functors} for the requirements on 'manipulator'. // ACCESSORS template <class ACCESSOR> int bdlat_typeCategoryAccessArray(const YOUR_TYPE& object, ACCESSOR& accessor); // Return the result of invoking the specified 'accessor' with the // specified 'object' (1st argument) and a 'bdlat_TypeCategory::Array' // tag object (2nd argument). If 'object' is not a 'bdlat' "array" // type, pass a 'bslmf::Nil' tag object as the second argument. See // {'ACCESSOR' Functors} for the requirements on 'accessor'. template <class ACCESSOR> int bdlat_typeCategoryAccessChoice(const YOUR_TYPE& object, ACCESSOR& accessor); // Return the result of invoking the specified 'accessor' with the // specified 'object' (1st argument) and a 'bdlat_TypeCategory::Choice' // tag object (2nd argument). If 'object' is not a 'bdlat' "choice" // type, pass a 'bslmf::Nil' tag object as the second argument. See // {'ACCESSOR' Functors} for the requirements on 'accessor'. template <class ACCESSOR> int bdlat_typeCategoryAccessCustomizedType(const YOUR_TYPE& object, ACCESSOR& accessor); // Return the result of invoking the specified 'accessor' with the // specified 'object' (1st argument) and a // 'bdlat_TypeCategory::CustomizedType' tag object (2nd argument). If // 'object' is not a 'bdlat' "customized type" type, pass a // 'bslmf::Nil' tag object as the second argument. See {'ACCESSOR' // Functors} for the requirements on 'accessor'. template <class ACCESSOR> int bdlat_typeCategoryAccessEnumeration(const YOUR_TYPE& object, ACCESSOR& accessor); // Return the result of invoking the specified 'accessor' with the // specified 'object' (1st argument) and a // 'bdlat_TypeCategory::Enumeration' tag object (2nd argument). If // 'object' is not a 'bdlat' "enumeration type" type, pass a // 'bslmf::Nil' tag object as the second argument. See {'ACCESSOR' // Functors} for the requirements on 'accessor'. template <class ACCESSOR> int bdlat_typeCategoryAccessNullableValue(const YOUR_TYPE& object, ACCESSOR& accessor); // Return the result of invoking the specified 'accessor' with the // specified 'object' (1st argument) and a // 'bdlat_TypeCategory::NullableValue' tag object (2nd argument). If // 'object' is not a 'bdlat' "nullable value" type, pass a 'bslmf::Nil' // tag object as the second argument. See {'ACCESSOR' Functors} for // the requirements on 'accessor'. template <class ACCESSOR> int bdlat_typeCategoryAccessSequence(const YOUR_TYPE& object, ACCESSOR& accessor); // Return the result of invoking the specified 'accessor' with the // specified 'object' (1st argument) and a // 'bdlat_TypeCategory::Sequence' tag object (2nd argument). If // 'object' is not a 'bdlat' "sequence" type, pass a 'bslmf::Nil' tag // object as the second argument. See {'ACCESSOR' Functors} for the // requirements on 'accessor'. template <class ACCESSOR> int bdlat_typeCategoryAccessSimple(const YOUR_TYPE& object, ACCESSOR& accessor); // Return the result of invoking the specified 'accessor' with the // specified 'object' (1st argument) and a 'bdlat_TypeCategory::Simple' // tag object (2nd argument). If 'object' is not a 'bdlat' "simple" // type, pass a 'bslmf::Nil' tag object as the second argument. See // {'ACCESSOR' Functors} for the requirements on 'accessor'. bdlat_TypeCategory::Value bdlat_typeCategorySelect( const YOUR_TYPE& object); // Return the *runtime* type category for the specified 'object'. The // behavior is undefined if 'bdlat_TypeCategory::e_DYNAMIC_CATEGORY' is // returned. Note that the compile time analog to this function // (template) is 'bdlat_TypeCategory::Select', a meta-function that // defines a type corresponding to the category tag class of // 'YOUR_TYPE'.
bdlat
type categories to which they belong. bdlat_TypeCategoryDeclareDynamic
trait and providing a VALUE
of 1, and bdlat
categories the type can assume. T
is recognized as a "dynamic" bdlat
type then bdlat_TypeCategory::Select<T>Type
is an alias for bdlat_TypeCategory::DynamicType
bdlat_TypeCategoryFunctions::select
function to provide the necessary runtime logic that determines its current runtime category. See Customization Points. bdlat
"dyanmic" category is illustrated in Example 3. bdlat_TypeCategoryDeclareDynamic
trait to designate a user-defined class as a "dynamic" type, doing so is the recommended practice. bdlat
category traits does not work on those platforms. bdlat
type categories -- an unusual configuration, but one that is allowed by the 'bdlat" type category framework. bdlat_TypeCategoryDeclareDynamic
trait is the only trait in this component that users are allowed to specialize. The behavior is undefined if any of the other meta-functions are specialized. bdlat_typecategory
framework provides facilities to control actions based on the bdlat
type category of the objects being used. Dispatching on type category can be achieved both at compile time and at runtime. Depending on that context, different facilities, having different restrictions/requirements are used. There are interesting differences when dealing with objects in the "dynamic" type category. bdlat
type categories and that we wish to examine it to the extent of determining into which type category it falls and what value it has. printCategoryAndValue
function that has a template parameter TYPE
: namespace BloombergLP { namespace mine { template <class TYPE> void printCategoryAndValue(bsl::ostream& stream, const TYPE& object); // Print the category of the specified 'object' followed by the value // of 'object' to the specified output 'stream'.
void printCategory(bsl::ostream& stream, bdlat_TypeCategory::Array) { stream << "Array"; } void printCategory(bsl::ostream& stream, bdlat_TypeCategory::Choice) { stream << "Choice"; } void printCategory(bsl::ostream& stream, bdlat_TypeCategory::CustomizedType) { stream << "CustomizedType"; } void printCategory(bsl::ostream& stream, bdlat_TypeCategory::DynamicType) { stream << "DynamicType"; } void printCategory(bsl::ostream& stream, bdlat_TypeCategory::Enumeration) { stream << "Enumeration"; } void printCategory(bsl::ostream& stream, bdlat_TypeCategory::NullableValue) { stream << "NullableValue"; } void printCategory(bsl::ostream& stream, bdlat_TypeCategory::Sequence) { stream << "Sequence"; } void printCategory(bsl::ostream& stream, bdlat_TypeCategory::Simple) { stream << "Simple"; }
template <class TYPE, class CATEGORY> void printValue(bsl::ostream& stream, const TYPE& object, CATEGORY ) { bdlb::PrintMethods::print(stream, object, 0, -1); } template <class TYPE> void printValue(bsl::ostream& stream, const TYPE& , bdlat_TypeCategory::DynamicType ) { stream << "Printing dynamic types requires extra work."; }
printCategoryAndValue
function in terms of the printCategory
and printValue
helper functions: template <class TYPE> void printCategoryAndValue(bsl::ostream& stream, const TYPE& object) { typedef typename bdlat_TypeCategory::Select<TYPE>::Type TypeCategory; printCategory(stream, TypeCategory()); stream << ": "; printValue(stream, object, TypeCategory()); } } // close package namespace } // close enterprise namespace
printCategoryAndValue
function on objects that fall in different (non-dynamic) type categories. using namespace BloombergLP; void runUsageExample1() { bsl::ostringstream oss; int intVal = 123; mine::printCategoryAndValue(oss, intVal); assert("Simple: 123" == oss.str()); oss.str(""); bdlb::NullableValue<int> nullableInt; mine::printCategoryAndValue(oss, nullableInt); assert("NullableValue: NULL" == oss.str()); oss.str(""); nullableInt = 321; mine::printCategoryAndValue(oss, nullableInt); assert("NullableValue: 321" == oss.str()); oss.str(""); bsl::vector<int> vec; vec.push_back(123); vec.push_back(345); vec.push_back(987); mine::printCategoryAndValue(oss, vec); assert("Array: [ 123 345 987 ]" == oss.str()); }
bdlat_TypeCategoryUtil
. Suppose we wish to examine the type category and value of an arbitrary bdlat
compatible object, as we did in Example 1. mine::PrintAccessor
, a functor that encapsulates the action to be taken: namespace BloombergLP { namespace mine { class PrintAccessor { bsl::ostream *d_stream_p; public: PrintAccessor(bsl::ostream *stream) : d_stream_p(stream) { assert(stream); } template <class TYPE> int operator()(const TYPE& , bslmf::Nil ) { *d_stream_p << "Nil"; return -1; } template <class TYPE> int operator()(const TYPE& object, bdlat_TypeCategory::Array) { *d_stream_p << "Array" << ": "; bdlb::PrintMethods::print(*d_stream_p, object, 0, -1); return 0; } template <class TYPE> int operator()(const TYPE& object, bdlat_TypeCategory::Choice) { *d_stream_p << "Choice" << ": "; bdlb::PrintMethods::print(*d_stream_p, object, 0, -1); return 0; } template <class TYPE> int operator()(const TYPE& object, bdlat_TypeCategory::CustomizedType) { *d_stream_p << "CustomizedType" << ": "; bdlb::PrintMethods::print(*d_stream_p, object, 0, -1); return 0; } template <class TYPE> int operator()(const TYPE& object, bdlat_TypeCategory::Enumeration) { *d_stream_p << "Enumeration" << ": "; bdlb::PrintMethods::print(*d_stream_p, object, 0, -1); return 0; } template <class TYPE> int operator()(const TYPE& object, bdlat_TypeCategory::NullableValue) { *d_stream_p << "NullableValue" << ": "; bdlb::PrintMethods::print(*d_stream_p, object, 0, -1); return 0; } template <class TYPE> int operator()(const TYPE& object, bdlat_TypeCategory::Sequence) { *d_stream_p << "Sequence" << ": "; bdlb::PrintMethods::print(*d_stream_p, object, 0, -1); return 0; } template <class TYPE> int operator()(const TYPE& object, bdlat_TypeCategory::Simple) { *d_stream_p << "Simple" << ": "; bdlb::PrintMethods::print(*d_stream_p, object, 0, -1); return 0; } }; } // close package namespace } // close enterprise namespace
operator()
includes an overload for bslmf::Nil
(as required) but does not include an overload for bdlat_TypeCategory::DynamicType
which is never reported as a runtime type category. bdlat_TypeCategoryUtil
to determine the type of a given object dispatch control to the corresponding overload of the accessor functor: using namespace BloombergLP; void runUsageExample2() { bsl::ostringstream oss; mine::PrintAccessor accessor(&oss); int intVal = 123; bdlat_TypeCategoryUtil::accessByCategory(intVal, accessor); assert("Simple: 123" == oss.str()); oss.str(""); bdlb::NullableValue<int> nullableInt; bdlat_TypeCategoryUtil::accessByCategory(nullableInt, accessor); assert("NullableValue: NULL" == oss.str()); oss.str(""); nullableInt = 321; bdlat_TypeCategoryUtil::accessByCategory(nullableInt, accessor); assert("NullableValue: 321" == oss.str()); oss.str(""); bsl::vector<int> vec; vec.push_back(123); vec.push_back(345); vec.push_back(987); bdlat_TypeCategoryUtil::accessByCategory(vec, accessor); LOOP_ASSERT(oss.str(), "Array: [ 123 345 987 ]" == oss.str()); oss.str(""); }
bdlat
"dyanmic" type category and show how its behavior is a generalization of what we have seen for the "static" bdlat
types. mine::MyDynamicType
, that can hold one of two value types: either a bsl::vector<char>
or a bsl::string
. namespace BloombergLP { namespace mine { class MyDynamicType { // This class can represent data in two forms: either a 'bsl::string' // or as a 'bsl::vector' of 'char' values. // PRIVATE DATA MEMBERS bsl::vector<char> d_vectorChar; // Note: Production code should use a bsl::string d_string; // union of object buffers. int d_selector; // 0 = vectorChar, 1 = string public: // MANIPULATORS void makeVectorChar() { d_selector = 0; } void makeString() { d_selector = 1; } bsl::vector<char>& theVectorChar() { assert(isVectorChar()); return d_vectorChar; } bsl::string& theString() { assert(isString()); return d_string; } // ACCESSORS bool isVectorChar() const { return 0 == d_selector; } bool isString() const { return 1 == d_selector; } const bsl::vector<char>& theVectorChar() const { assert(isVectorChar()); return d_vectorChar; } const bsl::string& theString() const { assert(isString()); return d_string; } }; } // close package namespace } // close enterprise namespace
bdlat
"array" type and when holding a string, the class is a bdlat
"simple" type. Since this type can be in two type categories (determined at runtime) this class is deemed a "dynamic" class (for calculations at compile time). bdlat_TypeCategoryDeclareDynamic
meta-function in the BloombergLP
namespace: namespace BloombergLP { template <> struct bdlat_TypeCategoryDeclareDynamic<mine::MyDynamicType> { enum { VALUE = 1 }; }; } // close enterprise namespace
bdlat_typeCategory(Manipulate|Access)(Array|Simple)
, each overloaded for our type, MyDynamicType
. namespace BloombergLP { namespace mine { bdlat_TypeCategory::Value bdlat_typeCategorySelect(const MyDynamicType& object) { if (object.isVectorChar()) { return bdlat_TypeCategory::e_ARRAY_CATEGORY; // RETURN } else if (object.isString()) { return bdlat_TypeCategory::e_SIMPLE_CATEGORY; // RETURN } assert(!"Reached"); // Note that this 'return' is never reached and hence the returned // value is immaterial. return bdlat_TypeCategory::e_SIMPLE_CATEGORY; } template <class MANIPULATOR> int bdlat_typeCategoryManipulateArray(MyDynamicType *object, MANIPULATOR& manipulator) { if (object->isVectorChar()) { return manipulator(&object->theVectorChar(), bdlat_TypeCategory::Array()); // RETURN } return manipulator(object, bslmf::Nil()); } template <class MANIPULATOR> int bdlat_typeCategoryManipulateSimple(MyDynamicType *object, MANIPULATOR& manipulator) { if (object->isString()) { return manipulator(&object->theString(), bdlat_TypeCategory::Simple()); // RETURN } return manipulator(object, bslmf::Nil()); } template <class ACCESSOR> int bdlat_typeCategoryAccessArray(const MyDynamicType& object, ACCESSOR& accessor) { if (object.isVectorChar()) { return accessor(object.theVectorChar(), bdlat_TypeCategory::Array()); // RETURN } return accessor(object, bslmf::Nil()); } template <class ACCESSOR> int bdlat_typeCategoryAccessSimple(const MyDynamicType& object, ACCESSOR& accessor) { if (object.isString()) { return accessor(object.theString(), bdlat_TypeCategory::Simple()); // RETURN } return accessor(object, bslmf::Nil()); } } // close package namespace } // close enterprise namespace
MyDynamicType
can achieve: "array" and "simple". void runUsageExample3()
{
Select
meta-function returns the expected value: assert(bdlat_TypeCategory::e_DYNAMIC_CATEGORY == static_cast<bdlat_TypeCategory::Value>( bdlat_TypeCategory::Select<mine::MyDynamicType>::e_SELECTION));
bsl::ostringstream oss; mine::MyDynamicType object; mine::printCategoryAndValue(oss, object); assert("DynamicType: Printing dynamic types requires extra work." == oss.str()); oss.str("");
bdlat
framework treats the object as a member of the "array" category and the PrintAccessor
we defined in Example 2 treats object
as a member of the "array" category: object.makeVectorChar(); assert(bdlat_TypeCategory::e_ARRAY_CATEGORY == bdlat_TypeCategoryFunctions::select(object)); object.theVectorChar().push_back('H'); object.theVectorChar().push_back('e'); object.theVectorChar().push_back('l'); object.theVectorChar().push_back('l'); object.theVectorChar().push_back('o'); mine::PrintAccessor accessor(&oss); int ret; ret = bdlat_TypeCategoryUtil::accessByCategory(object, accessor); assert(0 == ret); LOOP_ASSERT(oss.str(), "Array: \"Hello\"" == oss.str()); oss.str("");
object
to behave as a string and find that the bdlat
framework now considers object
to be the "simple" category: object.makeString(); assert(bdlat_TypeCategory::e_SIMPLE_CATEGORY == bdlat_TypeCategoryFunctions::select(object)); object.theString() = "World"; ret = bdlat_TypeCategoryUtil::accessByCategory(object, accessor); assert(0 == ret); assert("Simple: World" == oss.str()); oss.str(""); }
isVector
and a "simple" type when the object isString
.