|
Boost : |
From: Simon Buchan (simon_at_[hidden])
Date: 2005-10-19 01:46:43
Fernando Cacciola wrote:
> Reece Dunn wrote:
>
>>Fernando Cacciola wrote:
>>
>>>Sam Partington wrote:
>>>
>>>>[...]
>>
>>Why not use partial specialization so that optional< T > has the
>>semantic sugar, but optional< T & > does not? Or is this already the
>>case?
>>
>
> I'm not too fond of template classes that support different interfaces
> according to the properties of the template parameters. That just doesn't
> play along with generic programming where the type you optionalize can or
> cannot be a reference.
> Think of vector<bool> for instance.
> I rather keep looking for a consistent solution.
>
The difference being that vector<bool> has semantic (but not syntactic)
differences, while optional<T&> would have syntactic (but not semantic)
differences. And
template <class T>
optional<T> foo(optional<T> ot) {
...
ot = optional<T>(someTexpr);
...
}
would always work. Just the same as always using
iterator_traits<It>::value_type, not It::value_type.
Personally, though, I think dropping optional<T&> would be perfectly
acceptable. References behave differently to every other built-in type.
>
>>>A related note about the use of operator *
>>>
>>>You said that, even for optional<T&>, it is clear that this:
>>>
>>> *o = i;
>>>
>>>is UB if 'o' is uninitialized. And so there is no problem defining
>>>that assignment as really just the assignment of the underlying
>>>type, which in
>>>the case of optional<T&> doesn't rebind.
>>>
>>>Now I wonder, if instead of operator*, we used value() (or
>>>whatever), would
>>>it be just as clear?
>>>
>>>// Nullable interface
>>>
>>>*o = rb ; // assing 'b' to 'a'
>>>o = none ; // releases 'a'
>>>*o = rc ; // !!! UB !!! Cleary IMO
>>>
>>>// Container interface
>>>
>>>o.value() = rb ; // assing 'b' to 'a'
>>>o.reset() ; // releases 'a'
>>>o.value() = rc ; // !!! Still UB !!! �But cleary enough?
>>
>>I personally prefer the nullable interface as it is more intuitive
>>w.r.t.
>>smart pointer usage.
>> o.value() = b
>>reads to me like value() is returning a (temporary) return value,
>>then you
>>are assigning rb to that.
>>
>
> Me too!
>
It looks uglier, that's for sure. But that would suggest:
int a, b;
// set...
int& ra = a;
int& rb = b;
optional<int&> o = ra; // OK, binding
*o = rb; // OK, sets a to b
o = none;
*o = rb; // UB -- attempt to set none with value of rb
o = rb; // not UB -- rebind o to b
o = ra; // rebind again?
o = b; // rebind to refer to b?
This is starting to look *exactly* like a pointer, but more confusing.
What's the point? (pun intended, unfortunately)
Also:
template <class A, class B>
void foo()
{ optional<A> oa;
optional<B> ob;
A a = ...;
B b = ...;
// then code using any of:
oa = b;
oa = a;
ob = a;
ob = b;
oa = ob;
ob = oa;
}
foo<int&, int>();
foo<int, int&>();
How is the person who writes that supposed to keep up with what binds to
what?
[...]
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk