Re: [boost] [fusion] unpack into constructor?

Eric Niebler wrote:
I have a Fusion sequence. I want to create an object of type T using the elements of the sequence as arguments to the constructor. Is there an easy way? I can't tell my looking at the docs. I looked at the stuff in fusion/functional and couldn't find what I was looking for.
I don't think we've got anything that supports this directly at the moment. Is the sort of thing you are looking for? fused_ctor<T> fc; T t = fc(sequence); Where fused_ctor::operator()(Seq const&) breaks up the sequence into args for the T ctor. If thats the sort of thing, I think we should have something like this, I can cook something up over the next few days, once I've worked through a bit of my backlog :) Of course I may have missed an existing feature, which my co-authors might pick me up on... Cheers Dan ___________________________________________________________ Yahoo! Answers - Got a question? Someone out there knows the answer. Try it now. http://uk.answers.yahoo.com/

dan marsden wrote:
I have a Fusion sequence. I want to create an object of type T using the elements of the sequence as arguments to the constructor. Is there an easy way? I can't tell my looking at the docs. I looked at the stuff in fusion/functional and couldn't find what I was looking for.
Isn't that exactly what a Phoenix actor does? Regards Hartmut
I don't think we've got anything that supports this directly at the moment. Is the sort of thing you are looking for?
fused_ctor<T> fc; T t = fc(sequence);
Where fused_ctor::operator()(Seq const&) breaks up the sequence into args for the T ctor.
If thats the sort of thing, I think we should have something like this, I can cook something up over the next few days, once I've worked through a bit of my backlog :)
Of course I may have missed an existing feature, which my co-authors might pick me up on...
Cheers
Dan
___________________________________________________________ Yahoo! Answers - Got a question? Someone out there knows the answer. Try it now. http://uk.answers.yahoo.com/ _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Hartmut Kaiser wrote:
dan marsden wrote:
I have a Fusion sequence. I want to create an object of type T using the elements of the sequence as arguments to the constructor. Is there an easy way? I can't tell my looking at the docs. I looked at the stuff in fusion/functional and couldn't find what I was looking for.
Isn't that exactly what a Phoenix actor does?
Hartmut, are you saying this functionality has no place in Fusion?
I don't think we've got anything that supports this directly at the moment. Is the sort of thing you are looking for?
fused_ctor<T> fc; T t = fc(sequence);
Where fused_ctor::operator()(Seq const&) breaks up the sequence into args for the T ctor.
Yes, that's the thing.
If thats the sort of thing, I think we should have something like this, I can cook something up over the next few days, once I've worked through a bit of my backlog :)
Of course I may have missed an existing feature, which my co-authors might pick me up on...
Thanks, Dan. FWIW, I have my own solution for this now, so there's no rush. But I'm sure it'd come in handy eventually. -- Eric Niebler Boost Consulting www.boost-consulting.com

Eric Niebler wrote:
Hartmut Kaiser wrote:
dan marsden wrote:
I have a Fusion sequence. I want to create an object of
type T using
the elements of the sequence as arguments to the constructor. Is there an easy way? I can't tell my looking at the docs. I looked at the stuff in fusion/functional and couldn't find what I was looking for.
Isn't that exactly what a Phoenix actor does?
Hartmut, are you saying this functionality has no place in Fusion?
No. I just said, that a similar functionality is in Phoenix. Regards Hartmut

Eric Niebler wrote:
Hartmut Kaiser wrote:
dan marsden wrote:
I don't think we've got anything that supports this directly at the moment.
As long as we're talking about Fusion/functional - no we haven't.
Is the sort of thing you are looking for?
fused_ctor<T> fc; T t = fc(sequence);
Where fused_ctor::operator()(Seq const&) breaks up the sequence into args for the T ctor.
Yes, that's the thing.
OK, but why duplicate the unpacking of the Sequence? All it takes is yet another adapter encapsulating a type's ctor(s) in a function object to just use fusion::(invoke|fused)_function_object. E.g: // untested code for illustration only template<typename T> struct ctor { typedef T result_type; // [...] tricky nullary case with default ctor detection // omitted for simplicity template<typename T0> T operator(T0 & a0) const { return T(a0); } template<typename T0, typename T1> T operator(T0 & a0, T1 & a1) const { return T(a0,a1); } // [...] // Note: // Sequence elements are unpacked as lvalues, so const // qualifiers on the argument types of operator() can be // deduced }; Client code (at function scope): invoke_function_object( ctor<my_class>(), argseq ); Regards, Tobias

Tobias Schwinger wrote:
Eric Niebler wrote:
Is the sort of thing you are looking for?
fused_ctor<T> fc; T t = fc(sequence);
Yes, that's the thing.
OK, but why duplicate the unpacking of the Sequence?
All it takes is yet another adapter encapsulating a type's ctor(s) in a function object to just use fusion::(invoke|fused)_function_object. E.g:
<snip>
Client code (at function scope):
invoke_function_object( ctor<my_class>(), argseq );
Yes, that's exactly it. Now, put it in Fusion so I don't have to write a function object with N overloads. :-) -- Eric Niebler Boost Consulting www.boost-consulting.com

Eric Niebler wrote:
Tobias Schwinger wrote:
Eric Niebler wrote:
Is the sort of thing you are looking for?
fused_ctor<T> fc; T t = fc(sequence); Yes, that's the thing. OK, but why duplicate the unpacking of the Sequence?
All it takes is yet another adapter encapsulating a type's ctor(s) in a function object to just use fusion::(invoke|fused)_function_object. E.g:
<snip>
Client code (at function scope):
invoke_function_object( ctor<my_class>(), argseq );
Yes, that's exactly it. Now, put it in Fusion so I don't have to write a function object with N overloads. :-)
OK, and here's some preliminary code. Headers go to fusion/functional/adapter, the .cpp file is a test. Thanks to Peter for making me realize things can be easy, occasionally :-). Regards, Tobias /*============================================================================= Copyright (c) 2006-2007 Tobias Schwinger Use modification and distribution are subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). ==============================================================================*/ #if !defined(BOOST_FUSION_FUNCTIONAL_ADAPTER_LIMITS_HPP_INCLUDED) # define BOOST_FUSION_FUNCTIONAL_ADAPTER_LIMITS_HPP_INCLUDED # include <boost/fusion/sequence/container/vector/limits.hpp> # if !defined(BOOST_FUSION_UNFUSED_GENERIC_MAX_ARITY) # define BOOST_FUSION_UNFUSED_GENERIC_MAX_ARITY 6 # elif BOOST_FUSION_UNFUSED_GENERIC_MAX_ARITY > FUSION_MAX_VECTOR_SIZE # error "BOOST_FUSION_UNFUSED_GENERIC_MAX_ARITY > FUSION_MAX_VECTOR_SIZE" # endif # if !defined(BOOST_FUSION_UNFUSED_RVALUE_ARGS_MAX_ARITY) # define BOOST_FUSION_UNFUSED_RVALUE_ARGS_MAX_ARITY 6 # elif BOOST_FUSION_UNFUSED_RVALUE_ARGS_MAX_ARITY > FUSION_MAX_VECTOR_SIZE # error "BOOST_FUSION_UNFUSED_RVALUE_ARGS_MAX_ARITY > FUSION_MAX_VECTOR_SIZE" # endif # if !defined(BOOST_FUSION_UNFUSED_LVALUE_ARGS_MAX_ARITY) # define BOOST_FUSION_UNFUSED_LVALUE_ARGS_MAX_ARITY 6 # elif BOOST_FUSION_UNFUSED_LVALUE_ARGS_MAX_ARITY > FUSION_MAX_VECTOR_SIZE # error "BOOST_FUSION_UNFUSED_LVALUE_ARGS_MAX_ARITY > FUSION_MAX_VECTOR_SIZE" # endif # if !defined(BOOST_FUSION_UNFUSED_TYPED_MAX_ARITY) # define BOOST_FUSION_UNFUSED_TYPED_MAX_ARITY 6 # elif BOOST_FUSION_UNFUSED_TYPED_MAX_ARITY > FUSION_MAX_VECTOR_SIZE # error "BOOST_FUSION_UNFUSED_TYPED_MAX_ARITY > FUSION_MAX_VECTOR_SIZE" # endif # if !defined(BOOST_FUSION_CONSTRUCTOR_MAX_ARITY) # define BOOST_FUSION_CONSTRUCTOR_MAX_ARITY 6 # endif #endif /*============================================================================= Copyright (c) 2007 Tobias Schwinger Use modification and distribution are subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). ==============================================================================*/ #if !defined(BOOST_FUSION_FUNCTIONAL_ADAPTER_CONSTRUCTOR_HPP_INCLUDED) #if !defined(BOOST_PP_IS_ITERATING) #include <boost/preprocessor/iteration/iterate.hpp> #include <boost/preprocessor/repetition/enum_params.hpp> #include <boost/preprocessor/repetition/enum_binary_params.hpp> #include <boost/fusion/functional/adapter/limits.hpp> namespace boost { namespace fusion { template<typename T> class constructor { public: typedef T result_type; inline T operator()() const { return T(); } #define BOOST_PP_FILENAME_1 \ <boost/fusion/functional/adapter/constructor.hpp> #define BOOST_PP_ITERATION_LIMITS \ (1, BOOST_FUSION_CONSTRUCTOR_MAX_ARITY) #include BOOST_PP_ITERATE() }; }} #define BOOST_FUSION_FUNCTIONAL_ADAPTER_CONSTRUCTOR_HPP_INCLUDED #else // defined(BOOST_PP_IS_ITERATING) //////////////////////////////////////////////////////////////////////////////// // // Preprocessor vertical repetition code // //////////////////////////////////////////////////////////////////////////////// #define N BOOST_PP_ITERATION() template< BOOST_PP_ENUM_PARAMS(N, typename T) > inline T operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,T,& a)) const { return T(BOOST_PP_ENUM_PARAMS(N, a)); } #undef N #endif // defined(BOOST_PP_IS_ITERATING) #endif /*============================================================================= Copyright (c) 2007 Tobias Schwinger Use modification and distribution are subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). ==============================================================================*/ #include <boost/fusion/functional/adapter/constructor.hpp> #include <boost/detail/lightweight_test.hpp> #include <boost/bind.hpp> namespace fusion = boost::fusion; class X { int val_sum; public: X() : val_sum(0) { } X(int a) : val_sum(a) { } X(int a, int b) : val_sum(a + b) { } operator int() const { return this->val_sum; } }; class Y { int const & ref_a; Y(); // undefined public: Y(int & a) : ref_a(a) { } operator int() const { return this->ref_a; } }; int main() { int one = 1, two = 2; fusion::constructor<X> create_x; BOOST_TEST(create_x() == 0); BOOST_TEST(create_x(one) == 1); BOOST_TEST(create_x(one,two) == 3); fusion::constructor<Y> create_y; BOOST_TEST(create_y(one) == 1); BOOST_TEST(boost::bind(create_x,one,_1)(two) == 3); BOOST_TEST(boost::bind(create_x,1,_1)(two) == 3); return boost::report_errors(); }

Tobias Schwinger wrote:
// [...] tricky nullary case with default ctor detection // omitted for simplicity
Doh! It's not possible to detect default constructibility, correct? So we'd have to declare it as template<typename T, typename DefaultConstructible = mpl::false_> struct constructor; -- Tobias

Tobias Schwinger wrote:
Tobias Schwinger wrote:
// [...] tricky nullary case with default ctor detection // omitted for simplicity
Doh! It's not possible to detect default constructibility, correct?
So we'd have to declare it as
template<typename T, typename DefaultConstructible = mpl::false_> struct constructor;
No. If the interface is "construct<T>(sequence)", then you can dispatch on the size of the sequence. You'd only try to default construct when you pass an empty sequence. -- Eric Niebler Boost Consulting www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com

Eric Niebler wrote:
Tobias Schwinger wrote:
Tobias Schwinger wrote:
// [...] tricky nullary case with default ctor detection // omitted for simplicity
Doh! It's not possible to detect default constructibility, correct?
So we'd have to declare it as
template<typename T, typename DefaultConstructible = mpl::false_> struct constructor;
No. If the interface is "construct<T>(sequence)", then you can dispatch on the size of the sequence. You'd only try to default construct when you pass an empty sequence.
Why is there a need to detect a default constructor?

Peter Dimov wrote:
Eric Niebler wrote:
Tobias Schwinger wrote:
Tobias Schwinger wrote:
// [...] tricky nullary case with default ctor detection // omitted for simplicity
Doh! It's not possible to detect default constructibility, correct?
So we'd have to declare it as
template<typename T, typename DefaultConstructible = mpl::false_> struct constructor;
No. If the interface is "construct<T>(sequence)", then you can dispatch on the size of the sequence. You'd only try to default construct when you pass an empty sequence.
Why is there a need to detect a default constructor?
There isn't one, as far as I can tell. -- Eric Niebler Boost Consulting www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com

Peter Dimov wrote:
Eric Niebler wrote:
Tobias Schwinger wrote:
Tobias Schwinger wrote:
// [...] tricky nullary case with default ctor detection // omitted for simplicity
Doh! It's not possible to detect default constructibility, correct?
So we'd have to declare it as
template<typename T, typename DefaultConstructible = mpl::false_> struct constructor;
No. If the interface is "construct<T>(sequence)", then you can dispatch on the size of the sequence. You'd only try to default construct when you pass an empty sequence.
Why is there a need to detect a default constructor?
(I probably snipped away too much context...) A generic function object that constructs an arbitrary type would have to know (unless having variadic templates, or being able to define operator() as a nonmember function template). This generalization would be useful to e.g. say boost::bind( constructor<T>(), 55, _2, _1) or make the implementation of the discussed Fusion utility 'construct<T>(fusion_sequence)' as simple as template<typename T, typename FusionSequence> T construct<T>(FusionSequence & seq) { return invoke_function_object( constructor<T>(), seq); } (the other stuff exists already). Regards, Tobias

Tobias Schwinger wrote:
Peter Dimov wrote:
...
Why is there a need to detect a default constructor?
(I probably snipped away too much context...)
A generic function object that constructs an arbitrary type would have to know (unless having variadic templates, or being able to define operator() as a nonmember function template).
Umm. Why?

Peter Dimov wrote:
Tobias Schwinger wrote:
Peter Dimov wrote:
...
Why is there a need to detect a default constructor? (I probably snipped away too much context...)
A generic function object that constructs an arbitrary type would have to know (unless having variadic templates, or being able to define operator() as a nonmember function template).
Umm. Why?
OK, in the bind case nullary operator() can just be omitted (if there are no parameters there's no point to use bind in the first place). But for the Fusion sequence case that wrapper would have to be entirely generic (IOW allow nullary calls if there is an appropriate constructor), because the sequence can be empty. Regards, Tobias

Tobias Schwinger wrote:
Peter Dimov wrote:
Tobias Schwinger wrote:
Peter Dimov wrote: ...
Why is there a need to detect a default constructor? (I probably snipped away too much context...)
A generic function object that constructs an arbitrary type would have to know (unless having variadic templates, or being able to define operator() as a nonmember function template). Umm. Why?
OK, in the bind case nullary operator() can just be omitted (if there are no parameters there's no point to use bind in the first place).
But for the Fusion sequence case that wrapper would have to be entirely generic (IOW allow nullary calls if there is an appropriate constructor), because the sequence can be empty.
No. I just noticed it just works fine without - sorry for the noise. Regards, Tobias

Tobias Schwinger wrote:
Tobias Schwinger wrote:
Peter Dimov wrote:
Tobias Schwinger wrote:
Peter Dimov wrote: ...
Why is there a need to detect a default constructor? (I probably snipped away too much context...)
A generic function object that constructs an arbitrary type would have to know (unless having variadic templates, or being able to define operator() as a nonmember function template). Umm. Why? OK, in the bind case nullary operator() can just be omitted (if there are no parameters there's no point to use bind in the first place).
But for the Fusion sequence case that wrapper would have to be entirely generic (IOW allow nullary calls if there is an appropriate constructor), because the sequence can be empty.
No. I just noticed it just works fine without - sorry for the noise.
^ [ knowing whether T is default constructible, because the signature can be instantiated ] -- Tobias

Eric Niebler wrote:
Tobias Schwinger wrote:
Tobias Schwinger wrote:
// [...] tricky nullary case with default ctor detection // omitted for simplicity
Doh! It's not possible to detect default constructibility, correct?
So we'd have to declare it as
template<typename T, typename DefaultConstructible = mpl::false_> struct constructor;
No. If the interface is "construct<T>(sequence)", then you can dispatch on the size of the sequence. You'd only try to default construct when you pass an empty sequence.
True, but this is not the kind of interface the previous post was about. Regards, Tobias
participants (5)
-
dan marsden
-
Eric Niebler
-
Hartmut Kaiser
-
Peter Dimov
-
Tobias Schwinger