Quick Links: |
Provide a namespace for "value type" functions. More...
Classes | |
struct | bdlat_ValueTypeFunctions_Imp |
Namespaces | |
namespace | bdlat_ValueTypeFunctions |
bdlat_ValueTypeFunctions | namespace for "value type" functions |
namespace
, bdlat_ValueTypeFunctions
, defining functions that may be called on "value
types". assign
values to "value type" objects (ie., as if by using the assignment operator *lhs = rhs
), and reset
"value type" objects to their default state (i.e., as if each object was just constructed using its default constructor). bdlat
"value type" framework are required to have: bdlat
"value type" framework must define in the namespace where the type is defined, overloads of the following free function template and free frunction. Note that the placeholder 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 RHS_TYPE> int bdlat_valueTypeAssign(YOUR_TYPE *lhs, const RHS_TYPE& rhs); // Assign to the specified 'lhs' the value if the specified 'rhs'. // Return 0 on success and a non-zero value otherwise. If setting // 'lhs' to 'rhs' would violate any preconditions, a non-zero value is // returned. If (template parameter) 'RHS_TYPE' cannot be used to set // the value of 'lhs', a non-zero value is returned. void bdlat_valueTypeReset(YOUR_TYPE *object); // Reset the specified 'object' to that of its default state (i.e., to // 'YOUR_TYPE()').
bdlat
type infrastructures, the bdlat
"value" infrastructure does not require the setting of any traits, or definition of meta-functions, or creation of any typedef
s. For example, see bdlat_arrayfunctions
and bdlat_nullablevaluefunctions
. bdlat_valueTypeAssign
: bdlat_valueTypeAssign
function deal with a wide contract, even if the corresponding operation in YOUR_TYPE
has a narrow contract. Types having any of the following traits (see bdlat_typetraits
):
namespace BloombergLP { namespace mine { struct MyValueType { int d_int; double d_double; }; } // close package namespace } // close enterprise namespace
MyValueType
was rather terse, several methods are implicitly defined by the compiler: void f() { using namespace BloombergLP; mine::MyValueType a = { 1, 1.0 }; // aggregate braced initialization mine::MyValueType b(a); // implicit copy constructor assert(b.d_int == a.d_int); assert(b.d_double == a.d_double); a.d_int = 2; a.d_double = 3.14; b = a; // implicit copy assignment operator assert(b.d_int == a.d_int); assert(b.d_double == a.d_double); }
MyValueType
part of the bdlat
"value" framework. As such, it can be manipulated using the methods of bdlat_ValueTypeFunctions
: void myUsageScenario() { using namespace BloombergLP; mine::MyValueType x = { 7, 10.0 }; mine::MyValueType y = { 99, -1.0 }; assert(x.d_int != y.d_int); assert(x.d_double != y.d_double); int rc = bdlat_ValueTypeFunctions::assign(&x, y); assert(0 == rc); assert(x.d_int == y.d_int); assert(x.d_double == y.d_double); bdlat_ValueTypeFunctions::reset(&y); assert(x.d_int != y.d_int); assert(x.d_double != y.d_double); assert(int() == y.d_int); assert(double() == y.d_double); }
mine::MyValueType
to allow its value to be assigned from a bsl::pair<int, float>
object? Do do so, create your::YourValueType
which has an implicit conversion from bsl::pair<int, float>
: namespace BloombergLP { namespace your { struct YourValueType { int d_int; double d_double; YourValueType() : d_int() , d_double() { } YourValueType(const YourValueType& original) : d_int (original.d_int) , d_double(original.d_double) { } YourValueType(int intValue, double doubleValue) : d_int ( intValue) , d_double(doubleValue) { } YourValueType(const bsl::pair<int, double>& value) // IMPLICIT : d_int (value.first) , d_double(value.second) { } }; } // close package namespace } // close enterprise namespace
g()
below: void g() { using namespace BloombergLP; your::YourValueType a(1, 1.0); // value initialization your::YourValueType b(a); // implicit copy constructor assert(b.d_int == a.d_int); assert(b.d_double == a.d_double); a.d_int = 2; a.d_double = 3.14; b = a; // implicit copy assignment operator assert(b.d_int == a.d_int); assert(b.d_double == a.d_double); bsl::pair<int, double> value(4, 5.0); a = value; assert(4 == a.d_int); assert(5.0 == a.d_double); }
YourValueType
can be handled by the bdlat
"value" infrastructure in much the same way as we did for MyValueType
: void yourUsageScenario() { using namespace BloombergLP; int rc; your::YourValueType x( 7, 10.0); your::YourValueType y(99, -1.0); assert(x.d_int != y.d_int); assert(x.d_double != y.d_double); rc = bdlat_ValueTypeFunctions::assign(&x, y); assert(0 == rc); assert(x.d_int == y.d_int); assert(x.d_double == y.d_double); bdlat_ValueTypeFunctions::reset(&y); assert(x.d_int != y.d_int); assert(x.d_double != y.d_double); assert(int() == y.d_int); assert(float() == y.d_double);
bsl::pair<int, double>
, is provided, the bdlat
"value" infrastructure can also use that type to set the value of objects. bsl::pair<int, double> value(4, 5.0); rc = bdlat_ValueTypeFunctions::assign(&y, value); assert(0 == rc); assert(value.first == y.d_int); assert(value.second == y.d_double);
// Assign an incompatible type. rc = bdlat_ValueTypeFunctions::assign(&y, bsl::string("4, 5.0")); assert(0 != rc); }
their::TheirValueType
, having neither copy constructor nor copy assignment operator: namespace BloombergLP { namespace their { class TheirValueType { // DATA int d_int; double d_double; private: // NOT IMPLEMENTED TheirValueType(const TheirValueType& original); // = delete TheirValueType& operator=(const TheirValueType&); // = delete public: // CREATORS TheirValueType() : d_int() , d_double() { } // MANIPULATORS void setValue(const bsl::string& valueString); // ACCESSORS int intValue() const { return d_int; } double doubleValue() const { return d_double; } }; // MANIPULATORS void TheirValueType::setValue(const bsl::string& valueString) { bsl::string::size_type pos = valueString.find(','); BSLS_ASSERT(bsl::string::npos != pos); d_int = bsl::atoi(valueString.c_str()); d_double = bsl::atof(valueString.c_str() + pos + 1); } } // close package namespace } // close enterprise namespace
MyValueType
and YourValueType
: void h() { using namespace BloombergLP; their::TheirValueType a; // default constructor assert(0 == a. intValue()); assert(0.0 == a.doubleValue()); // their::TheirValueType b(a); // Error, no copy constructor their::TheirValueType c; // c = a; // Error, no copy assignment operator a.setValue("2, 3.14"); assert(2 == a. intValue()); assert(3.14 == a.doubleValue()); }
TheirValueType
lacks both copy construction and assignment, that type is not implicitly supported by the bdlat
"value" infrastructure. TheirValueType
can be made compatible with that infrastructure if "they" define the required overloads of bdlat_valueTypeAssign
and bdlat_valueTypeReset
in their
namespace: namespace BloombergLP { namespace their { int bdlat_valueTypeAssign(TheirValueType *lhs, const TheirValueType& rhs) { BSLS_ASSERT(lhs); bsl::ostringstream oss; oss << rhs.intValue() << ", " << rhs.doubleValue(); lhs->setValue(oss.str()); return 0; } int bdlat_valueTypeAssign(TheirValueType *lhs, const bsl::string& rhs) { BSLS_ASSERT(lhs); lhs->setValue(rhs); return 0; } // Overload for any other 'RHS_TYPE' to return an error. template <class RHS_TYPE> int bdlat_valueTypeAssign(TheirValueType *lhs, const RHS_TYPE& rhs) { BSLS_ASSERT(lhs); (void)rhs; return -999; // Pick a distinctive non-negative value. } void bdlat_valueTypeReset(TheirValueType *object) { BSLS_ASSERT(object); bsl::ostringstream oss; oss << int() << ", " << double(); object->setValue(oss.str()); } } // close package namespace } // close enterprise namespace
bdlat_valueTypeAssign
are defined above: TheirValueType
to be "assigned" to itself is required by the bdlat
"value" infrastructure. bsl::string
is not technically required by the infrastructure, but is a practical requirement because bsl::string
is the only way TheirValueType
can be changed from its default value. RHS_TYPE
so that, if any other types are passed, the code will compile (as required) but also unconditionally fail (as required). TheirValueType
can now be manipulated by the bdlat
"value" infrastructure in much the same manner as was done for MyValueType
and YourValueType
: void theirUsageScenario() { using namespace BloombergLP; their::TheirValueType x; their::TheirValueType y; int rc; rc = bdlat_ValueTypeFunctions::assign(&x, bsl::string(" 7, 10.0")); assert(0 == rc); rc = bdlat_ValueTypeFunctions::assign(&y, bsl::string("99, -1.0")); assert(0 == rc); assert(x.intValue() != y.intValue()); assert(x.doubleValue() != y.doubleValue()); rc = bdlat_ValueTypeFunctions::assign(&x, y); assert(0 == rc); assert(x.intValue() == y.intValue()); assert(x.doubleValue() == y.doubleValue()); bdlat_ValueTypeFunctions::reset(&y); assert(int() == y.intValue()); assert(float() == y.doubleValue()); // Assign an incompatible type. bsl::pair<int, double> value(4, 5.0); rc = bdlat_ValueTypeFunctions::assign(&y, value); assert( 0 != rc); assert(-999 == rc); }