Boost logo

Boost :

From: David Abrahams (dave_at_[hidden])
Date: 2004-11-16 19:54:22


"Gennadiy Rozental" <gennadiy.rozental_at_[hidden]> writes:

>> 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.

>> > Hmm. Well, I did not find it nor in docs. Why IMO it's most
>> > important part of functionality. I see it now in test. Why did you
>> > name function f_list? Why not just f as rest of them?
>>
>> Where are you seeing f_list?
>
> In your test program.

I honestly don't know why, but my guess is that it's named that way
to distinguish that it expects a named parameter bundle instead of
individual parameters.

>> > I meant "within brackets". My problem is that it's p[name |
>> > "abc"] while I would prefer something like p[name] | "abc".
>>
>> That's not doable in general. Suppose the argument was an int? What
>> is
>>
>> p[index] | 3
>>
>> ??
>
> Yeah,. I understand.it's not possible. But within brackets is not
> very good either IMO

Opinion noted.

>> > 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 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.

> 2. In case of "active" solution you actually do it once and then
> could reuse it for many different functions
>
> class Entry {
> };
>
> class Logger {
> public:
> template<Params>
> log( msg, Params p )
> {
> Entry e( msg );
> p.apply_to( e );
>
> e.flush();
> }
>
> template<Params>
> buffer( msg, Params p )
> {
> m_entries.push_back( Entry( msg ) );
> p.apply_to( m_entries.back() );
> }
>
> template<Params>
> buffer( multichunk_msg, Params p )
> {
> m_entries.push_back( Entry( multichunk_msg ) );
> p.apply_to( m_entries.back() );
> }
>
>
> vector<Entry> m_entries;
> };

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.

> Sorry. I still not sure I understand. Let me put it as following example:
>
>
> template<typename T>
> void log( std::string prefix, std::string name, std::string separ, T const&
> v )
> {
> std::cout << prefix << name << separ << v;
> }
>
>
> template<typename Params>
> void
> log( Params const& p )
> {
> log( p[prefix | "" ], p[name], p[separator | " = " ], p[value] );
> }
>
> Yeah. In this case keyword "value" couldn't be typed.

The light dawns?

> 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.

>> >> > This library instead invented special mechanism of imposing
>> >> > restrictions.
>> >>
>> >> Not really; it used a de-facto standard approach for passing
>> >> compile-time functions.
>> >
>> > Yeah. But in C++ de-facto standard approach for enforcing parameters
>> > types is to specify one.
>>
>> Unless you're writing a function template.
>
> 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>?

> In other case it should be typed.
>
>> > I do not know about python, but in c++ I prefer named interface
>> > wouldn't break by switching order of parameter specification.
>>
>> What do you mean by "break?" When parameter names are used there is
>> no restriction on parameter order.
>>
>> f(arg1, arg2, arg3, key5 = arg5, key6 = arg6, key4 = arg4)
>> ^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> positional position-independent.
>
> 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.

>> These two are related; it should be clear from what I've written
>> above. Your code can allow at most one of these (I didn't check):
>> either it allows unchecked types and there's no ability to control
>> overload resolution, or it doesn't support function templates with
>> keyword arguments. And unless you have some way to induce SFINAE,
>> you have no way to distinguish multiple overloads of the same
>> function name accepting different named parameter sets:
>>
>> int foo1( c_str name, float v, int i )
>> {
>> }
>>
>> int foo2( int id )
>
> But you sad "multiple overloads of the same function"
> Above should look like
> int foo1( int id )

It doesn't matter one whit. I just used the names foo1 and foo2 for
clarity. Change them both to food if you like!

>> {
>> }
>>
>> template<class Params>
>> int foo(Params const& params)
>> {
>> foo1( params[name], params[value], params[index] );
>> }
>>
>> template<class Params>
>> int foo(Params const& params) // error, foo already defined.
>> {
>> foo2( 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.

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.

>> 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.

>> Yeah, but you don't need PS to cause ETI and other issues on VC <=
>> 7.0
>
> Do we still care? Enough to affect the design/implementation?

Somebody cares.

>> > I wouldn't be using it. Why would I use canon to kill sparrow.
>>
>> Why would anyone kill a sparrow?!! ;-)
>
> It's just Russian saying I was trying to translate.

I was only kidding.

-- 
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk