Home | Libraries | People | FAQ | More |
The following converter signatures have been considered:
bool operator()(TypeIn const&, TypeOut&); //#1 void operator()(TypeIn const&, boost::optional<TypeOut>&); //#2 boost::optional<TypeOut> operator()(TypeIn const&); //#3
From the design perspective the signature #1 has the advantage of providing the best separation of concerns. Namely, it leaves the respective converter with only one task -- the actual task of conversion. In practice though that can result in unnecessary performance overhead. Namely, given an instance of TypeOut type is supplied from outside, a storage for that instance needs to be allocated and, most importantly, initialized. That initialization phase (which can be expensive) is an unnecessary overhead as, if the conversion operation succeeds, the initial value is overridden with the actual result, if it fails, then the value of the TypeOut instance is either meaningless or worse misleading.
The signature #2 avoids the initialization overhead by deploying boost::optional
's ability to allocate storage
without initializing it. Now the storage for TypeOut
is still allocated outside but it is not initialized. It is now converter's
responsibility to know how to initialize the TypeOut
instance and, when needed, to actually initialize it.
In practice it is usually easier than it might sound. For example, strtol()
-based
converter might have something along the following lines:
void operator()(char const* str_in, boost::optional<int>& result_out) const { char const* str_end = str_in + strlen(str_in); char* cnv_end = 0; long int result = ::strtol(str_in, &cnv_end, base_); if (INT_MIN <= result && result <= INT_MAX && cnv_end == str_end) result_out = int(result); }
The signature #3 has been briefly considered as aesthetically advantageous and more idiomatic. Unfortunately, it lacked automatic deduction of the TypeOut which, consequently, had to be specified explicitly. For different types of supported converters (class-based, plain old functions, lambdas) that complicated considerably the implementation of the Boost.Convert infrastructure and restricted implementation of the respective converters.