[Variant] Binary visitation and return type

Hi all, is there a means of using the binary visitation pattern provided by the Boost.Variant library and make the return type of the visitation process dependent on the types currently stored inside the visited variant object instances? I.e. I'm looking for some way to do the following: typedef boost::variant<unsigned long, long> variant_type; struct add_visitor : public .... { long operator()(long t1, long t2) { return t1 + t2; } template <typename T> unsigned long operator()(unsigned long t1, T t2) { return t1 + t2; } template <typename T> unsigned long operator()(T t1, unsigned long t2) { return t1 + t2; } }; variant_type term1 = 1L; variant_type term2 = 2UL; variant_type term3 = -2L; variant_type unsigned_result = boost::apply_visitor(add_visitor(), term1, term2); variant_type signed_result = boost::apply_visitor(add_visitor(), term1, term3); Is this possible with the current implementation? Regards Hartmut

Hartmut Kaiser wrote:
Hi all,
is there a means of using the binary visitation pattern provided by the Boost.Variant library and make the return type of the visitation process dependent on the types currently stored inside the visited variant object instances?
When I look at the current apply_visitor interface, I can't think of any: template<typename Visitor, typename Variant> typename Visitor::result_type apply_visitor(Visitor & visitor, Variant & operand); You would need something like the lazy function return type deduction in Phoenix: struct Visitor { template <typename Arg1, typename Arg2> struct result { typedef ... result_type; }; ... }; and template<typename Visitor, typename Variant> typename Visitor::result<???>::result_type apply_visitor(Visitor & visitor, Variant & operand); I really don't know if ??? (the real argument types) can be determined at compile time.
variant_type term1 = 1L; variant_type term2 = 2UL; variant_type term3 = -2L;
variant_type unsigned_result = boost::apply_visitor(add_visitor(), term1, term2); variant_type signed_result = boost::apply_visitor(add_visitor(), term1, term3);
Is this possible with the current implementation?
That's something different: here you assign again to a variant! Why don't you simply use boost::variant as return type for the visitor? Stefan

Stefan Slapeta wrote:
is there a means of using the binary visitation pattern provided by the Boost.Variant library and make the return type of the visitation process dependent on the types currently stored inside the visited variant object instances?
When I look at the current apply_visitor interface, I can't think of any:
template<typename Visitor, typename Variant> typename Visitor::result_type apply_visitor(Visitor & visitor, Variant & operand);
You would need something like the lazy function return type deduction in Phoenix:
struct Visitor { template <typename Arg1, typename Arg2> struct result { typedef ... result_type; };
... };
and
template<typename Visitor, typename Variant> typename Visitor::result<???>::result_type apply_visitor(Visitor & visitor, Variant & operand);
I really don't know if ??? (the real argument types) can be determined at compile time.
Sure. Actually I've expected to have something like that used in the binary visiting code...
variant_type term1 = 1L; variant_type term2 = 2UL; variant_type term3 = -2L;
variant_type unsigned_result = boost::apply_visitor(add_visitor(), term1, term2); variant_type signed_result = boost::apply_visitor(add_visitor(), term1, term3);
Is this possible with the current implementation?
That's something different: here you assign again to a variant! Why don't you simply use boost::variant as return type for the visitor?
Yes, you're right. I've simply choose a bad sample for what I was looking for. But it seems, you've got my point anyway. Regards Hartmut

Hartmut Kaiser wrote:
struct add_visitor : public .... { long operator()(long t1, long t2) { return t1 + t2; } template <typename T> unsigned long operator()(unsigned long t1, T t2) { return t1 + t2; } template <typename T> unsigned long operator()(T t1, unsigned long t2) { return t1 + t2; } };
BTW, the parameter mix you took here won't work this way. Unfortunately, I've never got a binary visitor running without heavily using enable_ifs! (I still don't understand what argument type is actually passed to a visitor...) Stefan

Hello Hartmut, serendipitous question - I was working on this very problem last night when I knocked off for the evening. The gist of my approach is to return another variant from the binary version of the static visitor that is bounded by a the permutations of the types of the two input variants. My plan is to then operate on the return value using the unary version of static visitor... Perhaps this isn't exactly what you had in mind but it's all I could come up with. Perhaps others will jump in and be able to suggest a better implementation? // a set of bounded type classes class A; class B; class C; . . . // a variant bounded by our bounded types typedef boost::variant<A, B, C> vertex_variant_t; // a class fully specialized for each ordered pair of bounded types template <typename tail_vertex_T, typename head_vertex_T> class edge_executor; // a variant bounded explicitly the fully-specialized permutations of A,B,C...N // here: P(3,2) = 3!/(3-2)!=6 // Can anyone think of a clever way to succinctly write this typedef for large P(n,r)? typedef boost::variant< edge_executor<A,B>, edge_executor<A,C>, edge_executor<B,C> edge_executor<B,A>, edge_executor<C,A>, edge_executor<C,B>
edge_executor_variant_t;
class construct_edge_executor_variant : public boost::static_visitor<edge_executor_variant_t> { public: template <typename tail_vertex_T, typename head_vertex_T> edge_executor_variant_t operator() (tail_vertex_T const&, head_vertex_T const&) { return edge_executor_variant_t( edge_executor<tail_vertex_T, head_vertex_T> ); } edge_executor_variant_t operator() (vertex_T const&) { return edge_executor_variant_t( edge_executor<vertex_T, vertex_T> ); } }; - HTH Chris "Hartmut Kaiser" <hartmutkaiser@t-online.de> wrote in message news:1Cc3LI-0VxnTU0@afwd00.sul.t-online.com...
Hi all,
is there a means of using the binary visitation pattern provided by the Boost.Variant library and make the return type of the visitation process dependent on the types currently stored inside the visited variant object instances?
I.e. I'm looking for some way to do the following:
typedef boost::variant<unsigned long, long> variant_type;
struct add_visitor : public .... { long operator()(long t1, long t2) { return t1 + t2; } template <typename T> unsigned long operator()(unsigned long t1, T t2) { return t1 + t2; } template <typename T> unsigned long operator()(T t1, unsigned long t2) { return t1 + t2; } };
variant_type term1 = 1L; variant_type term2 = 2UL; variant_type term3 = -2L;
variant_type unsigned_result = boost::apply_visitor(add_visitor(), term1, term2); variant_type signed_result = boost::apply_visitor(add_visitor(), term1, term3);
Is this possible with the current implementation?
Regards Hartmut
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Christopher D. Russell wrote:
The gist of my approach is to return another variant from the binary version of the static visitor that is bounded by a the permutations of the types of the two input variants. My plan is to then operate on the return value using the unary version of static visitor... Perhaps this isn't exactly what you had in mind but it's all I could come up with. Perhaps others will jump in and be able to suggest a better implementation?
Thanks for this hint. Returning a variant from the visitor seems to be an option for me, but I'll have to investigate it more thoroughly. Initially I've expected to find some kind of meta function allowing to specify the required return type (as used in Phoenix and as it was mentioned here already), but this may not be possible in the context of the Boost.Variant library. Thanks and regards Hartmut

I'm not sure I completely understand what information you're trying to get out of the binary static visitor. Is the intention to deduce a type signature from the ordered pair represented by the specific type stored in each of the two input variants? Or, if the intention to return an instance of this type initialized with data sourced from the two input variants? The pseudo code I posted previously is an attempt to address the later. Maybe a std::map<std::pair<int,int>, metafunction> where std::pair<int,int> is std::make_pair(variant_a.which(), variant_b.which()) would work without any visitation at all? An interesting little puzzle with some extremely useful applications. "Hartmut Kaiser" <hartmutkaiser@t-online.de> wrote in message news:1CcPcJ-1qZ4KG0@afwd00.sul.t-online.com...
Christopher D. Russell wrote:
The gist of my approach is to return another variant from the binary version of the static visitor that is bounded by a the permutations of the types of the two input variants. My plan is to then operate on the return value using the unary version of static visitor... Perhaps this isn't exactly what you had in mind but it's all I could come up with. Perhaps others will jump in and be able to suggest a better implementation?
Thanks for this hint. Returning a variant from the visitor seems to be an option for me, but I'll have to investigate it more thoroughly.
Initially I've expected to find some kind of meta function allowing to specify the required return type (as used in Phoenix and as it was mentioned here already), but this may not be possible in the context of the Boost.Variant library.
Thanks and regards Hartmut
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
participants (3)
-
Christopher D. Russell
-
Hartmut Kaiser
-
Stefan Slapeta