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 f1;
boost::shared_ptr 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 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, like a weak_future class? And then a const_weak_future?
I don't want to think about it...
Thanks,
Braddock Gaskill