
using the library primitives inside the "apply" function. After all, why not make "apply" a free function?
template <class Params> void apply(Params& p, Whatever x) { // use p's "passive" interface to operate on x }
This looks like good idea, but as it is you couldn't put it into library, since you don't know which interface to use to operate on x.
That's been my point all along. No matter how you arrange things, the apply function can't go in the library. AFAICT, our submission gives you all the tools a library could give to make writing such a function possible. What more could you want?
What you could do is to make above function to apply all params to x
template <class Params> void apply(Params& p, Whatever x) { for_each<Param>( do_apply_to(x) ); }
and user will be required to write do_apply functions:
void do_apply( name_param, A& a ) { a.m_name = name_param.value; }
void do_apply( suffix_param, A& a ) { a.m_name.append( name_param.value ); }
void do_apply( prefix_param, A& a ) { a.m_name.prepend( name_param.value ); }
You really want to write three overloads rather than a single apply function? It doesn't seem like a win to me.
It could. I did that.
Please show how the library can help with the "active" part. The passive library can be used to build an active component easily enough. I just don't see how the library can help with the apply call.
Yes. User will be required to implement all apply calls for all
1. What if both prefix and suffix above are optional. How would you implement above apply 2. What if I do not know about all possible grist to the name? What if I want to allow users to be able to extend set of possible "grists". In my proposition one could define own keyword and implement do_apply and that's it. parameters.
Note though:
1. "Passive" solution does require the same: one need to 'apply' (assign) named parameter value to the target at the point of usage (not in the library)
What is this obsession with OO? You are assuming that there's a target. In the general case, you're wrapping functions.
It's not an obsession. As I mention in my original post, in my experience I found most need in named parameter interface in constructors for some complex classes. There you have 'natural' target: this In case of functions passive solutions does look more attractive. Though in some cases (like one I disrobed above) I would still employ passive one.
2. In case of "active" solution you actually do it once and then could reuse it for many different functions
As I've repeatedly said, I don't see any way that any library could help you to build an active solution more than our proposal does already.
Traversing apply would help.
Ok. I slightly reworked my code see attached. Now it supports both typed and non-typed keywords. all in 120 lines (I am sure it could be made smaller by more effective mpl use). I also eliminated "keyword coupling". Now it should be as good in this regard as submitted library.
It's still not as good because you don't provide for overload restriction via SFINAE.
If you have named template parameter it should be non-typed.
I guess you're not aware of the problems of overly-general function templates. Suppose you want to use a named parameter interface for this overload set?
template <class T> void f(T*);
template <class T> void f(boost::shared_ptr<T>&);
Suppose you want to allow users to add new overloads, say for my_ptr<U>?
Following example works with my code: //////////////////////////////////////////////////////////////// // Example: #include <iostream> #include <boost/shared_ptr.hpp> namespace test { keyword<struct instance_t> instance; template<typename T> void foo_impl( T* t ) { std::cout << "non shared " << *t << std::endl; } template<typename T> void foo_impl( boost::shared_ptr<T> t ) { std::cout << "shared " << *t << std::endl; } template<class Params> void foo(Params const& params) { foo_impl( params[instance] ); } } int main() { using test::foo; using test::instance; int i = 5; foo( instance = &i ); foo( instance = boost::shared_ptr<float>( new float(1.2) ) ); return 0; }
Let consider an example of two optional parameters name, value. Then
foo( "abc", value = 5 ) works foo( value = 5 ) works foo( value = 5, "abc" ) doesn't work.
As it should be. Named parameters must always follow positional parameters. It's an easy rule to explain, and nobody gets confused.
Does it gets explained anywhere in docs?
template<class Params> int foo(Params const& params) { food( params[name], params[value], params[index] ); }
template<class Params> int foo(Params const& params) // error, foo already defined. { food( params[id] ); }
We don't need two. I would write:
template<class Params> int foo(Params const& params) { if( name and value present ) foo1( params[name], params[value], params[index] ); else foo1( params[index] ); }
No you can't. The two branches may not compile in the same instantiation. If no value was supplied and there's no default, accessing params[value] should be a compiler error.
It was pseudocode. It's a compile time if: if_<cond,invoke1,invoke2>::type::invoke( params );
Plus, now you have an intrusive solution. A major reason to use overloading is that you *don't* have to modify an existing function to add an overload.
Could you show in more details example for this case (including how you library solve the problem), then I could better comment it.
Yes. You can't develop keywords independently.
I do not see to many differences from your solution. You also need unique id for the keyword, which you then organize in ordered structure. So essentially getting the same result.
A unique name is much easier to come up with than a unique number. With numbers all the keywords need to coordinate.
You also need to coordinate by combining all keyword designators into keywords structure. Though I agree that types are better (not significantly, would it cost to use types instead of numbers I would prefer numbers)
Dave Abrahams
Gennadiy.