Boost logo

Boost Users :

From: Braddock Gaskill (braddock_at_[hidden])
Date: 2007-07-31 19:22:40


I am continuing work on a futures library for boost. future objects (as
currently considered by the C++ standards committee, in particular Peter
Dimov's proposal) have reference semantics, like many pimpl types.

I have some burning questions about const correctness.

Hypothetical reference-semantic example:

future f1;
future f2 = f1; //f2 refers to the same underlying object as f1
f2.set(42); //do something
assert(f1.get() == 42); // see, same underlying object

This is roughly equivalent to:
boost::shared_ptr<future_impl> f1;
boost::shared_ptr<future_impl> f2 = f1;

A std::vector<T>::iterator is an example of another type with reference
semantics.

So, say I have a simple future class:

class future_impl {
  public:
    bool get() const {return value_;}
    void set(bool value) {value_ = value;}
  private:
    bool value_;
};

class future { //not really a future, just example
  public:
    future() : impl_(new future_impl) {}
    future(const future &other) : impl_(other.impl_) {}
    bool get() const {return impl_->get();}
    // Set may not be const, but it does NOT really modify this class
    void set(bool value) {impl_->set(value);}
  private:
    boost::shared_ptr<future_impl> impl_;
};

I have made the future::set() method non-const, but it does NOT really modify
the underlying future class, only the future_impl class it refers to.

This makes life very difficult when it comes to passing futures by reference:

// alternative #1 - pass const future &
void f1(const future &f) {
  bool v = f.get(); // no problem, get() is const
  f.set(!v); // cannot do this, set() is not const
  
  // BUT I can bypass the const-ness trivially, so it is pointless
  future f2(f);
  f2.set(!v);
}

// alternative #2 - pass future &
// with #2, I can't do simple things like this:
// f2(future(f)); //ERROR: non-const reference from a temporary - irritating
void f2(future &f) {
  bool v = f.get(); // no problem, get() is const
  f.set(!v);
}

// alternative #3 - pass by value
// Constructing shared_ptr's is VERY inefficient
void f3(future f) {
  bool v = f.get(); // no problem, get() is const
  f.set(!v); // cannot do this, set() is not const
}

// alternative #4 - const_future base class with the subset of const methods?
// kinda like a const_iterator? seems klunky.
class const_future {bool get() const;};
class future : public const_future {void set(bool);}

Does anyone have any advice or ideas?

Oh, and then there is a possible need for something like a
weak_ptr<future_impl>, like a weak_future class? And then a const_weak_future?
I don't want to think about it...

Thanks,
Braddock Gaskill


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net