Boost logo

Boost :

From: Chris Weed (chrisweed_at_[hidden])
Date: 2006-06-05 10:04:59


Hi,
I'd also like to see apply_visitor with more arguments.
Is there a reason it is limited to 2?
Chris

On 6/5/06, Yuval Ronen <ronen_yuval_at_[hidden]> wrote:
> Hi Eric!
> It's good to see that you've got back to the list. For a long time now,
> there was no one to answer users' questions and comments, So I'm taking
> this (rare :-) ) opportunity to present my wish list for Boost.Variant.
>
> First of all, I'd like to say that I think it's a great library. I've
> become addicted to it... However, there are some things I think are missing.
>
> 1. add operator !=
>
> There's operator==, and adding operator!= would be both easy and useful.
>
> 2. apply_visitor should accept the visitor by value
>
> std algorithms (such as for_each) accept their functors by value, not by
> [const] reference. I think that visitors should be considered as
> variant's equivalent to std functors, and thus be passed by value. This
> will allow me to pass temporary visitor objects, which is a very common
> use case, just as with std functors. It will also allow you to delete
> the two versions of apply_visitor (one taking a reference, one taking a
> const reference), and leave only one.
>
> 3. add support for non-copyable types, a-la Boost.Optional's in-place
> factory
>
> I found myself needing a variant of non-copyable types, and had to
> resort to dynamic allocation to solve it. Luckily for me, it wasn't a
> performance-critical code, so I could live with it. But of course it's
> not optimal...
>
> 4. add more flavours of get()
>
> Currently the get<T>() function has the semantics of "return current
> value only if it is of type implicitly convertible to T". But there are
> other usages, even more useful than this (and if there are other get()s,
> the name of the original get() should be changed to, for example,
> get_implicit).
>
> One of them is "return current value only if it is exactly of type T
> (using type_info)". The function will not compile if T is not any of the
> variant's types. A possible name for it could be get_exact(), but of
> course there might be better names.
>
> Another usage I found useful is when all of the variant's types are
> implicitly convertible to a common T (e.g, they all inherit from T).
> This function will not compile if any of the variant's types can't be
> implicitly convertible to T, but if it does compile, then it ensures it
> can't fail in run-time (in contrast to get_implicit and get_exact, which
> can fail in run-time). A possible name is get_common().
>
> I've attached a file containing my implementation of get_exact and
> get_common, in case you're interested. All the preprocessor magic there
> is beyond my understanding, I just copied it from your code, and hope I
> didn't make any mistakes...
>
> 5. support for reference types
>
> I don't know if Boost.Variant currently supports reference types, nor am
> I certain it should, but it's a possibility...
> There was a debate about Boost.Optional's support for reference types,
> which reached no clear conclusion. Maybe you're familiar with the
> details, but if not, in short, the problem is with code such as
>
> int a = ...;
> int b = ...;
> optional<int &> x; // x in initialized to 'empty'
> x = a; // x is binded to a's reference
> x = b; // is x rebinded to b's reference, or is a assigned the value in b?
>
> The reason I bring it up here, is because I think it's relevant to
> Boost.Variant as well. Variant of reference types will raise the exact
> same questions, which should probably get the exact same answers. IOW,
> both the question of whether to support reference types, and the
> question of how to support them, should apply to both Boost.Optional and
> Boost.Variant uniformly. It's an open issue.
>
> 6. propose it for TR2
>
> For the benefit of all of us...
>
> Thanks again for a great library,
> Yuval
>
>
> #ifndef VariantGet_h
> #define VariantGet_h
>
> #include <Utils/Variant.h>
> #include <boost/mpl/assert.hpp>
> #include <boost/mpl/contains.hpp>
>
> namespace boost {
>
> template <typename T>
> struct get_common_visitor : public static_visitor<T>
> {
> T operator()(T t) { return t; }
> };
>
> template <typename T, typename Variant>
> typename add_reference<T>::type get_common(Variant &v)
> {
> get_common_visitor<typename add_reference<T>::type> visitor;
> return v.apply_visitor(visitor);
> }
>
> template <typename T, typename Variant>
> typename add_reference<const T>::type get_common(const Variant &v)
> {
> get_common_visitor<typename add_reference<const T>::type> visitor;
> return v.apply_visitor(visitor);
> }
>
> template <typename T, typename Variant>
> void assert_variant_has_type(const Variant &)
> {
> BOOST_MPL_ASSERT((mpl::contains<typename Variant::types, T>));
> }
>
> template <typename T>
> struct get_exact_visitor : public static_visitor<T>
> {
> T operator()(T t) { return t; }
> };
>
> template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
> inline typename add_pointer<U>::type get_exact(
> boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
> BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U))
> {
> assert_variant_has_type<U>(*operand);
> typedef typename add_pointer<U>::type U_ptr;
> if (!operand) return static_cast<U_ptr>(0);
> if (operand->type() != typeid(U)) return static_cast<U_ptr>(0);
>
> detail::variant::get_visitor<U> v;
> return operand->apply_visitor(v);
> }
>
> template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
> inline typename add_pointer<const U>::type get_exact(
> const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
> BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U))
> {
> assert_variant_has_type<U>(*operand);
> typedef typename add_pointer<const U>::type U_ptr;
> if (!operand) return static_cast<U_ptr>(0);
> if (operand->type() != typeid(U)) return static_cast<U_ptr>(0);
>
> detail::variant::get_visitor<const U> v;
> return operand->apply_visitor(v);
> }
>
> template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
> inline typename add_reference<U>::type get_exact(
> boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
> BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U))
> {
> typedef typename add_pointer<U>::type U_ptr;
> U_ptr result = get_exact<U>(&operand);
>
> if (!result)
> throw bad_get();
> return *result;
> }
>
> template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
> inline typename add_reference<const U>::type get_exact(
> const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
> BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U))
> {
> typedef typename add_pointer<const U>::type U_ptr;
> U_ptr result = get_exact<const U>(&operand);
>
> if (!result)
> throw bad_get();
> return *result;
> }
>
> } // namespace
>
> #endif /* ! defined VariantGet_h */
>
>
> _______________________________________________
> Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
>
>


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk