|
Boost : |
From: Dave Gomboc (dave_at_[hidden])
Date: 2003-08-31 22:12:59
> Here's a (contrived) example of how the implicit conversion breaks
> generic code:
>
[example snipped]
>
> The point is that optional<T> is not a T, and most notably, a template
> function will never perform the coercion. Replace the lines like
> B b = get<2>(args);
> in your example with real calls to, e.g.
> do_something( get<2>(args) )
> and do_something() is likely to fail if it's a template function
> (expecting a T and not an optional<T>).
Okay, you've demonstrated that it may not be possible to drop-in
optional<T> for T with zero code changes when T is not a scalar type.
(Usually, my Ts are! ;-) Nonetheless, it is at least still possible to
write generic code that accepts either T or the wrapped T, which is
definitely an improvement over writing a whack of special-casing code.
Dave
// code below compiles, runs cleanly with g++ 3.3 and intel 7.1 on linux
#include <exception>
#include <iostream>
#include <vector>
template <typename T>
class nilable {
public:
nilable(void) : nil_(true) {};
nilable(const T & value) : value_(value), nil_(false) {};
// rely on default destructor
// rely on default copy constructor
// rely on default assignment operator
bool nil(void) const { return nil_; };
operator T(void) const {
if (nil_) throw std::bad_cast();
return value_;
};
const T & unsafe_reference(void) const { return value_; };
T & unsafe_reference(void) { return value_; };
const T unsafe_value(void) const { return value_; };
T unsafe_value(void) { return value_; };
private:
T value_;
bool nil_;
};
template <typename container_type>
void output(const container_type & c) {
for (typename container_type::const_iterator
i(c.begin()); i != c.end(); ++i) {
std::cout << *i << '\n';
};
};
int main(void) {
std::vector<int> v;
v.push_back(1);
v.push_back(2);
output(v);
try {
nilable< std::vector<int> > nv(v);
//output(nv); // true, this fails
output(std::vector<int>(nv)); // but this succeeds!
nilable< std::vector<int> > nv2;
output(std::vector<int>(nv2)); // and this throws as expected.
} catch (std::bad_cast) {
std::cout << "Cannot convert from nil to value.\n";
};
};
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk