Boost logo

Boost :

From: Eric Friedman (ebf_at_[hidden])
Date: 2006-06-07 03:37:28


Chris,

I believe it was due to the complexity of implementing it :)

Seriously though, it would be a nice feature to have, but it was not
immediately obvious at the time how to easily implement "ternary"
visitation. Moreover, there wasn't the same compelling set of use cases
as there is with binary visitation. Let me know if there is, though.

Eric

Chris Weed wrote:
> 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
>>
>>
>
> _______________________________________________
> 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