Boost logo

Boost :

Subject: Re: [boost] Boost review of the Convert library is ongoing
From: alex (alexhighviz_at_[hidden])
Date: 2014-05-20 07:15:25


>> ... This is about needing to specify what the "contract" for a converter
is.

>In my view there is no "contract for converter"... apart from the
>*requirement* it is a "callable" with a certain signature.

That is indeed exactly where we disagree.

>
>> Conversion to/from string requires a different contract than
>> conversion between types, encryption or conversion from Celsius to
>> Fahrenheit.
>
>I fail to see how/why these mentioned different type
>conversions/transformations "require different contracts".

Perhaps it is better to say 'would benefit from different contracts'.

For instance:

type-to-type converters would benefit from contracts that specify mechanisms
for checking for reversibility, loss of precision, overflow, etc.
type-string converters would benefit from contracts that specify mechanisms
for giving formatting instructions
unit-to-unit converters would benefit from all kinds of consistency and
equivalence test... see the Boost Unit library
encryptions converters would benefit from contracts that specify mechanisms
to specify/query encryption strength

>> The user still needs to supply a Default Construction function it is just
>> not the default constructor. I can see that this requirement follows from
>> the stringstream implementation.
>
>No, it's not a requirement of std::sstream but rather imposed by
>boost::convert::from.
>

Yes, but why? Isn't the underlying reason that sstream requires a reference?

my_type val;
stream >> val;

>> But it does not seem a reasonable
>> requirement for a generic converter (nor is the requirement of Copy
>> Constructible). All you can reasonably require is some function that
creates
>> a TypeOut from a TypeIn.
>

>I was not able to come up with a better implementation that would not have
>those requirements. If you have such an implementation, I'll incorporate
>it gladly.
>

How about reducing the API to the following? The only requirement on TypeOut
would be the requirements put by boost::optional (or your closely related
result-type).

api.hpp
#include <boost/optional.hpp>
namespace boost
template<typename TypeOut> struct convert
  template<typename TypeIn, typename Converter>
  static boost::optional<TypeOut> from(TypeIn const& in, Converter const&
converter)
  {
     boost::optional<TypeOut> out;
     converter(in, out);
     return out;
  }
};
}

In sstream.hpp you would have(with some simplification)

template<typename T> struct convert_default_maker
{
  static T make() { return T(); }
};

// in sstream.hpp
template<TypeIn, TypeOut>
void boost::basic_stringstream_converter::operator()(const TypeIn& in,
boost::optional<TypeOut>& out)
{
  TypeOut out_value = boost::convert_default_maker<TypeOut>::make();
  stream_.str(std::basic_string< char_type>());
  stream_ << in;
  stream_ >> out_value;
  out = boost::make_optional(!stream_.fail(), out_value);
}

And for class with expensive constructor:
 
template<T> struct large_vector
{
  large_vector(const T& v) : m_vector(v, 1000000){}
  std::vector<T> m_vector;
};

template<TypeIn, TypeOut>
void boost::large_vector_converter operator() (const TypeIn& in, boost::
optional <TypeOut>& out)
{
  try {
     out = large_vector< TypeIn >(in);
  } catch() {
    out = boost::none;
  }
}
}


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk