> 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";
    };

};


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Reply via email to