开发者

Custom iterator which converts values before saving it

开发者 https://www.devze.com 2022-12-31 08:15 出处:网络
A typical forward iterator is expected to implement following methods: value_type& operator*(); value_type* operator->();

A typical forward iterator is expected to implement following methods:

value_type& operator*();
value_type* operator->();

I'm writing a custom iterator for a custom container where user expects to see a value_type different from representation of the value inside a container. So when returning a value_type value to user I convert it from inner representation to user-expected value_type. It is easy to implement inside mentioned members.

Could you advice how to handle l-values? Where can 开发者_JAVA技巧I handle conversion of value_type to inner representation when user assigns values to iterator in syntax like *it = value_type(5)?

I thought of returning a functor but I dislike this idea becaues of non-usual syntax on caller's side.


If you're returning a reference, then you can't convert and return a reference unless you store the converted value, at which point I begin to question the point of an internal representation. I'm not sure if what you want is even possible. An example of this is vector<bool>, which is legendary because it doesn't work properly. If the standards committee can't make such a container work, it's probably not a great idea.


You might want to take a look into the implementation of the std::vector<bool> specialization iterators, as they tackle the same problem. Note that with time, the specialization has been frown upon mainly because it does not comply with the container requirements (the iterators don't provide references to the actual contained type, but a proxy value), and that will also be a problem with your implementation.

The other possible approach is using a regular container but having the stored type accept implement the assignment/conversions to and from the user expected types. If that is not possible with your current stored type, you can write a wrapper for it.

A simplified wrapper (you will need to work on it to make it work):

template <typename T, typename U>
class wrapper
{
public:
   typedef T store_type;
   typedef U value_type;
   wrapper() : stored() {}
   wrapper( value_type const & v ) 
      : stored( convert<store_type>(v) {}
   wrapper& operator=( value_type const & value ) { // or pass-by-value
      stored = convert<store_type>(value); // or however you can convert them
      return *this;
   }
   operator value_type() const { // I don't quite like this, if possible use explicit conversions
      return convert<value_type>(stored);
   }
private:
   store_type stored; // maybe storage is handled externally and this can be pointer/ref.
};
// For the simple test double<->int conversion static cast suffices
template <typename T, typename U>
T convert( U in ) {
   return static_cast<T>(in); 
}
int main() {
   std::vector< wrapper<double,int> > v;
   v.push_back( 10 );
   int x = v[0];
   v[0] = 5;

   std::vector< wrapper<int,double> > v2;
   v.push_back( 10.5 );
   double y = v2[0];
   v2[0] = 11.3;
}
0

精彩评论

暂无评论...
验证码 换一张
取 消