[parameter] some extensions to Boost.Parameter

Hello, I've played with some extensions to Boost.Parameter and would like to know if there is any interest to have any of them polished / rolled back into the library. I have found these extensions useful when using ArgumentPacks directly rather than using Boost.Parameter macros like BOOST_PARAMETER_FUNCTION, BOOST_PARAMETER_CONSTRUCTOR,... (I am using the library in this particular way because of reduced compile times and (IMO) cleaner library code (although user-side code takes a slight hit)). Here are brief descriptions of the extensions: *1* Keywords/Tags with fixed types These are intended for keywords/tags that are always associated with a certain type of argument. operator= of a fixed-type keyword always return a tagged argument whose value_type is the fixed type. This has the benefit of moving any type conversions to the call site, which allows *3* Implementing this involved splitting the keyword class into typed_keyword and untyped_keyword, with the commonalities extracted into a keyword_base class. It also introduces a corresponding new macro, BOOST_PARAMETER_TYPED_NAME. *2* Default-default arguments When a keyword always has the same default value, I found it useful to put the default value into the Tag definition (in the form of a static member function that returns that default value). The definition is made using a macro - this is an example use case: BOOST_PARAMETER_TYPED_NAME_WDEFAULT(label,const std::string,"") If a ArgumentPack args does not contain an explicit value for _label, args[_label] will return std::string(""). I'm not sure what the right response to e.g., args[label|"something"] should be. *3* Make ArgumentPacks constructible from other ArgumentPacks. I basically added a constructor to arg_list that does allows something like the following: // this will return an appropriate arg_list type, containing four tagged_args // the four tags are all typed (*1*) and with default default values(*2*) typedef argument_pack<tag::label, tag::size, tag::position, tag::background>::type argument_pack_type; window(const argument_pack_type &args); In the above case, e.g., window(( _label="label", _size=size_type(100,100) )) would call window with default-default values for position and background. The benefit here is that the implementation of window doesn't need to be templated (which is helpful in some cases), and you don't need to write any forwarding functions (or use BOOST_PARAMETER_FUN). *4* Overloading operator() for typed keywords Instead of writing, e.g.: window (( _size=size_type(100,100), _position=position_type(0,0) )) , we can write window (( _size(100,100), _position(0,0) )) I accomplished this by adding a delayed_constructor class which holds references to the arguments (e.g., 100, 100) and is convertible to the Tag's value_type (e.g. size_type). The 'conversion' is done constructing an instance of the value_type using the arguments. The delayed_constructor is then stored in a tagged_argument object instead of the usual reference to the value_type. I had to hack tagged_argument and arg_list to work with delayed_constructor, which was in some ways similar to how tagged_argument and arg_list are made to work with the `maybe` class. This leads me to believe that tagged_argument and arg_list would benefit from having a specified extension interface into which things like `maybe` and `delayed_constructor` could hook into, rather than being so tightly coupled. The proof-of-concept implementation for all these things can be found at: http://svn.boost.org/svn/boost/sandbox/guigl/boost/parameter/ To avoid clashing with Boost.Parameter, I made the above extensions in renamed classes (e.g., typed_arg_list and typed_tagged_argument). Please let me know if there is any interest. Kind regards, Stjepan

on Tue Oct 28 2008, "Stjepan Rajko" <stipe-AT-asu.edu> wrote:
Hello,
I've played with some extensions to Boost.Parameter and would like to know if there is any interest to have any of them polished / rolled back into the library. I have found these extensions useful when using ArgumentPacks directly rather than using Boost.Parameter macros like BOOST_PARAMETER_FUNCTION, BOOST_PARAMETER_CONSTRUCTOR,... (I am using the library in this particular way because of reduced compile times
That's a bit of a surprise. What kind of difference in compile time are you seeing?
and (IMO) cleaner library code
Could you show some examples? Answers to these two questions could help me evaluate the merits of integrating this functionality into the library.
(although user-side code takes a slight hit)).
That shouldn't be necessary, even if you forego the macros.
Here are brief descriptions of the extensions:
*1* Keywords/Tags with fixed types These are intended for keywords/tags that are always associated with a certain type of argument. operator= of a fixed-type keyword always return a tagged argument whose value_type is the fixed type.
This has the benefit of moving any type conversions to the call site,
Might be interesting if we can integrate that into the macros for the cases when you specify a fixed type. This sounds vaguely similar to what we have to do for the Python binding functionality, except that we do the "type fixing" post-facto.
which allows *3*
Implementing this involved splitting the keyword class into typed_keyword and untyped_keyword, with the commonalities extracted into a keyword_base class. It also introduces a corresponding new macro, BOOST_PARAMETER_TYPED_NAME.
*2* Default-default arguments When a keyword always has the same default value, I found it useful to put the default value into the Tag definition (in the form of a static member function that returns that default value). The definition is made using a macro - this is an example use case:
BOOST_PARAMETER_TYPED_NAME_WDEFAULT(label,const std::string,"")
If a ArgumentPack args does not contain an explicit value for _label, args[_label] will return std::string(""). I'm not sure what the right response to e.g., args[label|"something"] should be.
Compilation error?
*3* Make ArgumentPacks constructible from other ArgumentPacks.
Aren't they already?
I basically added a constructor to arg_list that does allows something like the following:
// this will return an appropriate arg_list type, containing four tagged_args // the four tags are all typed (*1*) and with default default values(*2*) typedef argument_pack<tag::label, tag::size, tag::position, tag::background>::type argument_pack_type;
window(const argument_pack_type &args);
In the above case, e.g., window(( _label="label", _size=size_type(100,100) )) would call window with default-default values for position and background.
The benefit here is that the implementation of window doesn't need to be templated (which is helpful in some cases), and you don't need to write any forwarding functions (or use BOOST_PARAMETER_FUN).
Ohhh.... so you're saying any two argument packs with the same keywords and types would be inter-convertible, regardless of argument order? That makes some sense.
*4* Overloading operator() for typed keywords
Instead of writing, e.g.: window (( _size=size_type(100,100), _position=position_type(0,0) )) , we can write window (( _size(100,100), _position(0,0) ))
Pretty cool. This looks like it overlaps with deduced parameters a lot, though.
I accomplished this by adding a delayed_constructor class which holds references to the arguments (e.g., 100, 100) and is convertible to the Tag's value_type (e.g. size_type). The 'conversion' is done constructing an instance of the value_type using the arguments. The delayed_constructor is then stored in a tagged_argument object instead of the usual reference to the value_type.
I had to hack tagged_argument and arg_list to work with delayed_constructor, which was in some ways similar to how tagged_argument and arg_list are made to work with the `maybe` class. This leads me to believe that tagged_argument and arg_list would benefit from having a specified extension interface into which things like `maybe` and `delayed_constructor` could hook into, rather than being so tightly coupled.
The proof-of-concept implementation for all these things can be found at: http://svn.boost.org/svn/boost/sandbox/guigl/boost/parameter/
To avoid clashing with Boost.Parameter, I made the above extensions in renamed classes (e.g., typed_arg_list and typed_tagged_argument).
Please let me know if there is any interest.
I'd have to see what Daniel thinks. It would also be interesting to know if anyone else in the community has wanted this functionality. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

David Abrahams wrote:
on Tue Oct 28 2008, "Stjepan Rajko" <stipe-AT-asu.edu> wrote:
Hello,
I've played with some extensions to Boost.Parameter and would like to know if there is any interest to have any of them polished / rolled back into the library.tions of the extensions:
*1* Keywords/Tags with fixed types These are intended for keywords/tags that are always associated with a certain type of argument. operator= of a fixed-type keyword always return a tagged argument whose value_type is the fixed type.
This one would be interesting. I was always puzzled of which type of argument I get when using named arguments with a default.
*2* Default-default arguments When a keyword always has the same default value, I found it useful to put the default value into the Tag definition (in the form of a static member function that returns that default value). The definition is made using a macro - this is an example use case:
BOOST_PARAMETER_TYPED_NAME_WDEFAULT(label,const std::string,"")
This would be great, too.
If a ArgumentPack args does not contain an explicit value for _label, args[_label] will return std::string(""). I'm not sure what the right response to e.g., args[label|"something"] should be.
Compilation error?
IMO, it would be better if the "something" value overrode the default-default value designated in the macro above. The keyword can be used with more than one function and some of the functions may want to use different default values.
*3* Make ArgumentPacks constructible from other ArgumentPacks.
Aren't they already?
I basically added a constructor to arg_list that does allows something like the following:
// this will return an appropriate arg_list type, containing four tagged_args // the four tags are all typed (*1*) and with default default values(*2*) typedef argument_pack<tag::label, tag::size, tag::position, tag::background>::type argument_pack_type;
window(const argument_pack_type &args);
In the above case, e.g., window(( _label="label", _size=size_type(100,100) )) would call window with default-default values for position and background.
The benefit here is that the implementation of window doesn't need to be templated (which is helpful in some cases), and you don't need to write any forwarding functions (or use BOOST_PARAMETER_FUN).
That's very nice. Could be very useful if one wants to hide the function into a separate cpp.
*4* Overloading operator() for typed keywords
Instead of writing, e.g.: window (( _size=size_type(100,100), _position=position_type(0,0) )) , we can write window (( _size(100,100), _position(0,0) ))
Pretty cool.
This looks like it overlaps with deduced parameters a lot, though.
I accomplished this by adding a delayed_constructor class which holds references to the arguments (e.g., 100, 100) and is convertible to the Tag's value_type (e.g. size_type). The 'conversion' is done constructing an instance of the value_type using the arguments. The delayed_constructor is then stored in a tagged_argument object instead of the usual reference to the value_type.
Do I understand correctly that in the latter case "window (( _size(100,100), _position(0,0) ))" the arguments are not actually constructed unless they are requested in the window constructor? If so, this is just great! Looking forward to see it in the official Boost.Parameter library. What I'm also missing is the ability to iterate through an argument pack with the ability to acquire argument names. Basically, I want to be able to transform an argument pack into something like a map< string, any >. I can see there is some support for argument names, but I don't see how I could iterate through the argument pack.

On Tue, Oct 28, 2008 at 3:07 PM, Andrey Semashev <andrey.semashev@gmail.com> wrote:
David Abrahams wrote:
on Tue Oct 28 2008, "Stjepan Rajko" <stipe-AT-asu.edu> wrote:
If a ArgumentPack args does not contain an explicit value for _label, args[_label] will return std::string(""). I'm not sure what the right response to e.g., args[label|"something"] should be.
Compilation error?
IMO, it would be better if the "something" value overrode the default-default value designated in the macro above. The keyword can be used with more than one function and some of the functions may want to use different default values.
I like this suggestion.
*3* Make ArgumentPacks constructible from other ArgumentPacks. [...]
The benefit here is that the implementation of window doesn't need to be templated (which is helpful in some cases), and you don't need to write any forwarding functions (or use BOOST_PARAMETER_FUN).
That's very nice. Could be very useful if one wants to hide the function into a separate cpp.
This was exactly what I needed it for :-)
*4* Overloading operator() for typed keywords
Instead of writing, e.g.: window (( _size=size_type(100,100), _position=position_type(0,0) )) , we can write window (( _size(100,100), _position(0,0) )) [...]
Do I understand correctly that in the latter case "window (( _size(100,100), _position(0,0) ))" the arguments are not actually constructed unless they are requested in the window constructor? If so, this is just great! Looking forward to see it in the official Boost.Parameter library.
Yep, you got it.
What I'm also missing is the ability to iterate through an argument pack with the ability to acquire argument names. Basically, I want to be able to transform an argument pack into something like a map< string, any >. I can see there is some support for argument names, but I don't see how I could iterate through the argument pack.
I think it would be useful to write an include file that makes ArgumentPacks conforming fusion sequences. With that, what you're trying to solve should be doable using fusion::for_each. Thanks for your feedback! Stjepan

on Tue Oct 28 2008, "Stjepan Rajko" <stipe-AT-asu.edu> wrote:
*3* Make ArgumentPacks constructible from other ArgumentPacks. [...]
The benefit here is that the implementation of window doesn't need to be templated (which is helpful in some cases), and you don't need to write any forwarding functions (or use BOOST_PARAMETER_FUN).
That's very nice. Could be very useful if one wants to hide the function into a separate cpp.
This was exactly what I needed it for :-)
You can always forward to a separate implementation function, per http://www.boost.org/doc/libs/1_36_0/libs/parameter/doc/html/index.html#para... -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On Tue, Oct 28, 2008 at 2:08 PM, David Abrahams <dave@boostpro.com> wrote:
on Tue Oct 28 2008, "Stjepan Rajko" <stipe-AT-asu.edu> wrote:
I have found these extensions useful when using ArgumentPacks directly rather than using Boost.Parameter macros like BOOST_PARAMETER_FUNCTION, BOOST_PARAMETER_CONSTRUCTOR,... (I am using the library in this particular way because of reduced compile times
That's a bit of a surprise. What kind of difference in compile time are you seeing?
Nothing too dramatic. In the following experiment: http://article.gmane.org/gmane.comp.lib.boost.devel/178703 ... the results for a simple test scenario gave the following times: user: [test_parameter_compilation.o] 0.000195 system: [test_parameter_compilation.o] 0.000030 user: [test_parameter_dispatch_compilation.o] 0.000555 system: [test_parameter_dispatch_compilation.o] 0.000041 test_parameter_compilation corresponds to using ArgumentPacks directly, and test_parameter_dispatch_compilation uses BOOST_PARAMETER_CONSTRUCTOR (perhaps for BOOST_PARAMETER_FUN the difference is even smaller or non-existent)
and (IMO) cleaner library code
Could you show some examples?
Sure. My use case is a GUI library that tries to make it easy to implement new widgets. Widgets can be put together by stacking behaviors in an inheritance chain. For example, a button uses the following base class: class button; typedef view::active_colored< view::solid_background< view::clickable<button, view::positioned<> > > > button_base_type; - each of the view:: templates listed adds a behavior to the button widget, and they are implemented by inheriting the next behavior in the chain (in this case, button will inherit active_colored which will inherit solid_background which will inherit clickable which will inherit positioned...). Here is the button constructor: class button : public button_base_type { public: typedef button_base_type base_type; template<typename ArgumentPack> button(const ArgumentPack &args) : button_base_type(args) {} ... I.e., the constructor takes an ArgumentPack and forwards it to its base class. The base class will perhaps pick off some arguments and forward the pack to its base, etc. For example, solid_background does this: template<typename BaseView=base> class solid_background : public BaseView { public: typedef BaseView base_type; template<typename ArgumentPack> solid_background(const ArgumentPack &args) : base_type(args) , m_background_color(args[_background]) {} ... I have found that the direct use of ArgumentPacks makes this inheritance-chaining design quite nice/clean to implement. AFAICT, using the macro-based interface would have required two classes per view/behavior (an implementation class, and a class that uses BOOST_PARAMETER_CONSTRUCTOR) - this is because any of these classes can be the top-level class. That alone was reason enough for me not to investigate that route further - I'm not sure whether any difficulty would arise from having to specify that a class can receive a parameter intended for it, or intended for the base class.
Answers to these two questions could help me evaluate the merits of integrating this functionality into the library.
(although user-side code takes a slight hit)).
That shouldn't be necessary, even if you forego the macros.
I think I'm stuck with requiring double parenthesis, and I don't know how to take advantage of, e.g., deduced parameters.
Here are brief descriptions of the extensions:
*1* Keywords/Tags with fixed types These are intended for keywords/tags that are always associated with a certain type of argument. operator= of a fixed-type keyword always return a tagged argument whose value_type is the fixed type.
This has the benefit of moving any type conversions to the call site,
Might be interesting if we can integrate that into the macros for the cases when you specify a fixed type. This sounds vaguely similar to what we have to do for the Python binding functionality, except that we do the "type fixing" post-facto.
I think this would be relatively easy and safe (in a non-breaking change sense) to add in. [...]
BOOST_PARAMETER_TYPED_NAME_WDEFAULT(label,const std::string,"")
If a ArgumentPack args does not contain an explicit value for _label, args[_label] will return std::string(""). I'm not sure what the right response to e.g., args[label|"something"] should be.
Compilation error?
Perhaps. I think the alternative that Andrey Semashev suggested is also interesting, where "something" is chosen if the label is not explicitly provided. That would allow the default-default functionality to also be useful in scenarios where the default value is fixed "almost always".
*3* Make ArgumentPacks constructible from other ArgumentPacks.
Aren't they already?
I basically added a constructor to arg_list that does allows something like the following:
// this will return an appropriate arg_list type, containing four tagged_args // the four tags are all typed (*1*) and with default default values(*2*) typedef argument_pack<tag::label, tag::size, tag::position, tag::background>::type argument_pack_type;
window(const argument_pack_type &args);
In the above case, e.g., window(( _label="label", _size=size_type(100,100) )) would call window with default-default values for position and background.
The benefit here is that the implementation of window doesn't need to be templated (which is helpful in some cases), and you don't need to write any forwarding functions (or use BOOST_PARAMETER_FUN).
Ohhh.... so you're saying any two argument packs with the same keywords and types would be inter-convertible, regardless of argument order? That makes some sense.
Yes - a source pack could be converted to a target pack type as long as the source contains a superset of the tags needed for the target (or any missing tags have a default-default value).
*4* Overloading operator() for typed keywords
Instead of writing, e.g.: window (( _size=size_type(100,100), _position=position_type(0,0) )) , we can write window (( _size(100,100), _position(0,0) ))
Pretty cool.
This looks like it overlaps with deduced parameters a lot, though.
Yes, there is overlap. If deduced parameters were available (are they, without the macros?), you could do: window (( size_type(100,100), position_type(0,0) )) except `window (( _size(100,100), _position(0,0) ))` would also work when size_type and position_type are the same type.
Please let me know if there is any interest.
I'd have to see what Daniel thinks. It would also be interesting to know if anyone else in the community has wanted this functionality.
Thanks for taking a look! Best, Stjepan

on Tue Oct 28 2008, "Stjepan Rajko" <stipe-AT-asu.edu> wrote:
What kind of difference in compile time are you seeing?
Nothing too dramatic. In the following experiment: http://article.gmane.org/gmane.comp.lib.boost.devel/178703
... the results for a simple test scenario gave the following times: user: [test_parameter_compilation.o] 0.000195 system: [test_parameter_compilation.o] 0.000030 user: [test_parameter_dispatch_compilation.o] 0.000555 system: [test_parameter_dispatch_compilation.o] 0.000041
test_parameter_compilation corresponds to using ArgumentPacks directly, and test_parameter_dispatch_compilation uses BOOST_PARAMETER_CONSTRUCTOR (perhaps for BOOST_PARAMETER_FUN the difference is even smaller or non-existent)
I presume you actually meant BOOST_PARAMETER_FUNCTION? -- Dave Abrahams BoostPro Computing http://www.boostpro.com

on Tue Oct 28 2008, "Stjepan Rajko" <stipe-AT-asu.edu> wrote:
I.e., the constructor takes an ArgumentPack and forwards it to its base class. The base class will perhaps pick off some arguments and forward the pack to its base, etc.
The Accumulators library uses the same pattern. It would be interesting to see if your changes can simplify anything Eric did there. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

on Tue Oct 28 2008, "Stjepan Rajko" <stipe-AT-asu.edu> wrote:
On Tue, Oct 28, 2008 at 2:08 PM, David Abrahams <dave@boostpro.com> wrote:
on Tue Oct 28 2008, "Stjepan Rajko" <stipe-AT-asu.edu> wrote:
I have found these extensions useful when using ArgumentPacks directly rather than using Boost.Parameter macros like BOOST_PARAMETER_FUNCTION, BOOST_PARAMETER_CONSTRUCTOR,... (I am using the library in this particular way because of reduced compile times
That's a bit of a surprise. What kind of difference in compile time are you seeing?
Nothing too dramatic. In the following experiment: http://article.gmane.org/gmane.comp.lib.boost.devel/178703
... the results for a simple test scenario gave the following times: user: [test_parameter_compilation.o] 0.000195 system: [test_parameter_compilation.o] 0.000030 user: [test_parameter_dispatch_compilation.o] 0.000555 system: [test_parameter_dispatch_compilation.o] 0.000041
test_parameter_compilation corresponds to using ArgumentPacks directly, and test_parameter_dispatch_compilation uses BOOST_PARAMETER_CONSTRUCTOR (perhaps for BOOST_PARAMETER_FUN the difference is even smaller or non-existent)
and (IMO) cleaner library code
Could you show some examples?
Sure. My use case is a GUI library that tries to make it easy to implement new widgets. Widgets can be put together by stacking behaviors in an inheritance chain. For example, a button uses the following base class:
class button;
typedef view::active_colored< view::solid_background< view::clickable<button, view::positioned<> > > > button_base_type;
- each of the view:: templates listed adds a behavior to the button widget, and they are implemented by inheriting the next behavior in the chain (in this case, button will inherit active_colored which will inherit solid_background which will inherit clickable which will inherit positioned...). Here is the button constructor:
class button : public button_base_type { public: typedef button_base_type base_type;
template<typename ArgumentPack> button(const ArgumentPack &args) : button_base_type(args) {} ...
I.e., the constructor takes an ArgumentPack and forwards it to its base class. The base class will perhaps pick off some arguments and forward the pack to its base, etc. For example, solid_background does this:
template<typename BaseView=base> class solid_background : public BaseView { public: typedef BaseView base_type;
template<typename ArgumentPack> solid_background(const ArgumentPack &args) : base_type(args) , m_background_color(args[_background]) {} ...
I have found that the direct use of ArgumentPacks makes this inheritance-chaining design quite nice/clean to implement. AFAICT, using the macro-based interface would have required two classes per view/behavior (an implementation class, and a class that uses BOOST_PARAMETER_CONSTRUCTOR) - this is because any of these classes can be the top-level class. That alone was reason enough for me not to investigate that route further - I'm not sure whether any difficulty would arise from having to specify that a class can receive a parameter intended for it, or intended for the base class.
I don't see why that means the top-level class needs to have an ArgumentPack ctor. class button : public button_base_type { public: typedef button_base_type base_type; // takes up to 12 parameters MY_GUI_GENERATE_CTOR(button, 12, button_base_type);
Answers to these two questions could help me evaluate the merits of integrating this functionality into the library.
(although user-side code takes a slight hit)).
That shouldn't be necessary, even if you forego the macros.
I think I'm stuck with requiring double parenthesis,
You shouldn't be.
and I don't know how to take advantage of, e.g., deduced parameters.
They are only applicable when the types of possible arguments are sharply distinct. Is that your situation?
Here are brief descriptions of the extensions:
*1* Keywords/Tags with fixed types These are intended for keywords/tags that are always associated with a certain type of argument. operator= of a fixed-type keyword always return a tagged argument whose value_type is the fixed type.
This has the benefit of moving any type conversions to the call site,
Might be interesting if we can integrate that into the macros for the cases when you specify a fixed type. This sounds vaguely similar to what we have to do for the Python binding functionality, except that we do the "type fixing" post-facto.
I think this would be relatively easy and safe (in a non-breaking change sense) to add in.
Looking forward to seeing that.
BOOST_PARAMETER_TYPED_NAME_WDEFAULT(label,const std::string,"")
If a ArgumentPack args does not contain an explicit value for _label, args[_label] will return std::string(""). I'm not sure what the right response to e.g., args[label|"something"] should be.
Compilation error?
Perhaps. I think the alternative that Andrey Semashev suggested is also interesting, where "something" is chosen if the label is not explicitly provided.
Fine with me; that would've been the other obvious choice.
Ohhh.... so you're saying any two argument packs with the same keywords and types would be inter-convertible, regardless of argument order? That makes some sense.
Yes - a source pack could be converted to a target pack type as long as the source contains a superset of the tags needed for the target (or any missing tags have a default-default value).
And, I hope, the types of the source pack have to be convertible to the types of the target pack.
*4* Overloading operator() for typed keywords
Instead of writing, e.g.: window (( _size=size_type(100,100), _position=position_type(0,0) )) , we can write window (( _size(100,100), _position(0,0) ))
Pretty cool.
This looks like it overlaps with deduced parameters a lot, though.
Yes, there is overlap. If deduced parameters were available (are they, without the macros?),
Yes.
you could do:
window (( size_type(100,100), position_type(0,0) ))
except `window (( _size(100,100), _position(0,0) ))` would also work when size_type and position_type are the same type.
Yes.
Please let me know if there is any interest.
I'd have to see what Daniel thinks. It would also be interesting to know if anyone else in the community has wanted this functionality.
Thanks for taking a look!
Always nice to have someone else carrying our work forward! -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On Wed, Oct 29, 2008 at 4:34 PM, David Abrahams <dave@boostpro.com> wrote:
on Tue Oct 28 2008, "Stjepan Rajko" <stipe-AT-asu.edu> wrote:
I have found that the direct use of ArgumentPacks makes this inheritance-chaining design quite nice/clean to implement. AFAICT, using the macro-based interface would have required two classes per view/behavior (an implementation class, and a class that uses BOOST_PARAMETER_CONSTRUCTOR) - this is because any of these classes can be the top-level class. That alone was reason enough for me not to investigate that route further - I'm not sure whether any difficulty would arise from having to specify that a class can receive a parameter intended for it, or intended for the base class.
I don't see why that means the top-level class needs to have an ArgumentPack ctor.
Every class needs a constructor that takes an ArgumentPack because it can be inherited from, and needs to be able to receive the ArgumentPack from the derived class. If I wanted to allow users to call the constructor in a more friendly way, then every class that could be a top-level class would also need a constructor like you suggest below (and 'every class' would need to turn into a pair of classes because we can't delegate to another constructor in the same class, no?). Ideally, I would want to allow things like this: typedef view::solid_background< view::positioned<> > colored_block; some_window << new colored_block(...); BUT... I might have other reasons why I might require a boiler-plate top-level class, in which case I might do something like what you suggest below.
class button : public button_base_type { public: typedef button_base_type base_type;
// takes up to 12 parameters MY_GUI_GENERATE_CTOR(button, 12, button_base_type);
does MY_GUI_GENERATE_CTOR expand to template<typename T0> button(const T0 &t0) : button_base_type((t0)) {} template<typename T0, typename T1> button(const T0 &t0, const T1 &t1) : button_base_type((t0, t1)) {} ... ? [...]
and I don't know how to take advantage of, e.g., deduced parameters.
They are only applicable when the types of possible arguments are sharply distinct. Is that your situation?
No, I was just curious in general.
Here are brief descriptions of the extensions:
*1* Keywords/Tags with fixed types These are intended for keywords/tags that are always associated with a certain type of argument. operator= of a fixed-type keyword always return a tagged argument whose value_type is the fixed type.
This has the benefit of moving any type conversions to the call site,
Might be interesting if we can integrate that into the macros for the cases when you specify a fixed type. This sounds vaguely similar to what we have to do for the Python binding functionality, except that we do the "type fixing" post-facto.
I think this would be relatively easy and safe (in a non-breaking change sense) to add in.
Looking forward to seeing that.
I'm sorry, I think I misunderstood your comment. I thought you were talking about adding something to the library that allows things like BOOST_PARAMETER_TYPED_NAME(arg, int) - which is easy and I have done. But are you talking about BOOST_PARAMETER_FUNCTION( (void), foo, tag, (required (arg, int) ) (optional (arg2, double, 1.5) ) ) ... and how the expansion of that could be altered? I looked at the preprocessing file but got pretty lost, I think it might take me a while before I understand how it works. [...]
Ohhh.... so you're saying any two argument packs with the same keywords and types would be inter-convertible, regardless of argument order? That makes some sense.
Yes - a source pack could be converted to a target pack type as long as the source contains a superset of the tags needed for the target (or any missing tags have a default-default value).
And, I hope, the types of the source pack have to be convertible to the types of the target pack.
I've been using this with typed keywords, in which the types should be identical if the tags match. When conversions are necessary, because tagged_argument stores the argument by reference you end up with a dangling reference because the converted temporary goes out of scope before the function actually gets called. If you wanted conversions, you would need tagged_argument to store by value at least in this case (in which case it might be more efficient for arg_list to store the tagged_argument by reference... but I'm not sure whether that would run into the same temporary lifetime problems or other issues). [...]
Yes, there is overlap. If deduced parameters were available (are they, without the macros?),
Yes.
How? In order for the following to work: window (( size_type(100,100), position_type(0,0) )) ...I would at least have to overload the comma operator for these two types to return... what? Or, if I used something like the MY_GUI_GENERATE_CTOR macro and took `window (size_type(100,100), position_type(0,0) )`, how does the constructor assemble the ArgumentPack from the two types? Best, Stjepan

on Thu Oct 30 2008, "Stjepan Rajko" <stipe-AT-asu.edu> wrote:
On Wed, Oct 29, 2008 at 4:34 PM, David Abrahams <dave@boostpro.com> wrote:
on Tue Oct 28 2008, "Stjepan Rajko" <stipe-AT-asu.edu> wrote:
I have found that the direct use of ArgumentPacks makes this inheritance-chaining design quite nice/clean to implement. AFAICT, using the macro-based interface would have required two classes per view/behavior (an implementation class, and a class that uses BOOST_PARAMETER_CONSTRUCTOR) - this is because any of these classes can be the top-level class. That alone was reason enough for me not to investigate that route further - I'm not sure whether any difficulty would arise from having to specify that a class can receive a parameter intended for it, or intended for the base class.
I don't see why that means the top-level class needs to have an ArgumentPack ctor.
Every class needs a constructor that takes an ArgumentPack because it can be inherited from, and needs to be able to receive the ArgumentPack from the derived class. If I wanted to allow users to call the constructor in a more friendly way, then every class that could be a top-level class would also need a constructor like you suggest below (and 'every class' would need to turn into a pair of classes because we can't delegate to another constructor in the same class, no?).
Ideally, I would want to allow things like this:
typedef view::solid_background< view::positioned<> > colored_block;
some_window << new colored_block(...);
BUT... I might have other reasons why I might require a boiler-plate top-level class, in which case I might do something like what you suggest below.
Sorry, maybe I didn't understand correctly, but I thought classes like button below were "top level" and were not chained like the elements of button_base_type. If that's wrong *and* classes like button have interesting construction behavior of their own, then yes, they would have to both pass argument packs through and have a base class to which they can delegate "real" construction.
class button : public button_base_type { public: typedef button_base_type base_type;
// takes up to 12 parameters MY_GUI_GENERATE_CTOR(button, 12, button_base_type);
does MY_GUI_GENERATE_CTOR expand to
template<typename T0> button(const T0 &t0) : button_base_type((t0)) {}
template<typename T0, typename T1> button(const T0 &t0, const T1 &t1) : button_base_type((t0, t1)) {}
...
?
Something like that.
[...]
and I don't know how to take advantage of, e.g., deduced parameters.
They are only applicable when the types of possible arguments are sharply distinct. Is that your situation?
No, I was just curious in general.
Look at the documentation for Boost.Python's def(...) function and class_<...> template.
Here are brief descriptions of the extensions:
*1* Keywords/Tags with fixed types These are intended for keywords/tags that are always associated with a certain type of argument. operator= of a fixed-type keyword always return a tagged argument whose value_type is the fixed type.
This has the benefit of moving any type conversions to the call site,
Might be interesting if we can integrate that into the macros for the cases when you specify a fixed type. This sounds vaguely similar to what we have to do for the Python binding functionality, except that we do the "type fixing" post-facto.
I think this would be relatively easy and safe (in a non-breaking change sense) to add in.
Looking forward to seeing that.
I'm sorry, I think I misunderstood your comment. I thought you were talking about adding something to the library that allows things like BOOST_PARAMETER_TYPED_NAME(arg, int) - which is easy and I have done. But are you talking about
BOOST_PARAMETER_FUNCTION( (void), foo, tag, (required (arg, int) ) (optional (arg2, double, 1.5) ) )
... and how the expansion of that could be altered?
Yes.
I looked at the preprocessing file but got pretty lost, I think it might take me a while before I understand how it works.
Daniel is responsible for most of that code; maybe he can help.
[...]
Ohhh.... so you're saying any two argument packs with the same keywords and types would be inter-convertible, regardless of argument order? That makes some sense.
Yes - a source pack could be converted to a target pack type as long as the source contains a superset of the tags needed for the target (or any missing tags have a default-default value).
And, I hope, the types of the source pack have to be convertible to the types of the target pack.
I've been using this with typed keywords, in which the types should be identical if the tags match. When conversions are necessary, because tagged_argument stores the argument by reference you end up with a dangling reference because the converted temporary goes out of scope before the function actually gets called. If you wanted conversions, you would need tagged_argument to store by value at least in this case (in which case it might be more efficient for arg_list to store the tagged_argument by reference... but I'm not sure whether that would run into the same temporary lifetime problems or other issues).
Hm.
[...]
Yes, there is overlap. If deduced parameters were available (are they, without the macros?),
Yes.
How?
Sorry, no time to explain right now, but you can see examples in libs/parameter/test/deduced.cpp and libs/parameter/test/deduced_dependent_predicate.cpp. I suggest also reading the reference docs on ParameterSpec's -- Dave Abrahams BoostPro Computing http://www.boostpro.com
participants (3)
-
Andrey Semashev
-
David Abrahams
-
Stjepan Rajko