Subject: Re: [boost] [interfaces] Boost Interface Library (2004?)
From: Daniel Larimer (dlarimer_at_[hidden])
Date: 2011-02-11 23:03:52
On Feb 11, 2011, at 11:08 AM, Domagoj Saric wrote:
> "Daniel Larimer" <dlarimer_at_[hidden]> wrote in message news:C97AB2D0.21251%dlarimer_at_gmail.com...
>> What trade offs should be made?
> As always, (preferably) none :)
> If in practice some have to be made, for a low level library, 'power' and efficiency are primary concerns...
>> Macro-based or template-based?
> As always, 'avoid macros'...but, again, in practice some amount of macros will probably be unavoidable for a library like this (if verbosity/duplication is to be minimized)...
>> 1) Each method becomes a public boost::function with the proper
>> signature. This completely separates how things can be dispatched at the
>> expense of the size of the interface object. Great for long-lived objects,
>> not so great for small 'structs'.
> As a general possibility/an additional layer this may be useful somewhere (although I can't think of where) but to use/force it as the general implementation for all interfaces would just be a 'genocidal overkill' (regardless of the longevity of the objects)...especially with the current 'not so happy' boost::function implementation (see http://lists.boost.org/Archives/boost/2010/10/172593.php ...)...
> I'm not even sure where such an 'idiom' would fit or how it would be called as then the individual 'functions' would each have their own state (held in/by a boost::function<> object) as opposed to all sharing a common 'state' - the object whose interface they represent...
I do not like the boost::function problems either, it was more of a notional. There is always this(http://www.codeproject.com/KB/cpp/fastdelegate2.aspx) drop in replacement for boost::function. (What do people on this list think of these other delegates?). Then there is the super-fast, super-light weight FastDelegate by Don Clugston.
The challenge is that templates are great for calculating types, but manipulating and creating names is beyond its ability and requires either hand coding or the pre-processor. So to create a class with 'shared state' requires creating defining a method with a given name and param types. This can only be done if the entire specification uses the pre-processor.
( (ReturnType) (method1) ( (int)(arg1), (int)(arg2),.. ) ),
( (ReturnType) (method2) ( (int)(arg1), (int)(arg2),.. ) ),
This solution is very similar to what Boost.Interfaces did, everything is in the macro. This can achieve the most efficient solution, but in my mind the syntax is so bad that I would never want to touch it. Dealing with commas etc is also hard with these kind of macros. Ideally the preprocessor would only specify the names and the template code would deduce all of the types. Unfortunately, I am at a loss on how to efficiently let the templates deduce the types for a given name without using a macro to specify all possible partial specializations for each name resulting in template bloat. This may be possible with C++0x veridic templates, but messy in C++03. Compile times are important to me.
>> 2) Each method simply stores a member function pointer that must be
>> bound to the single 'this' used for all methods. This uses less memory, but
>> still is equivalent to a 'struct of pointers'.
> This still wouldn't be a 'struct of pointers' because member function pointers (i.e. their binary representation) are 'implementation defined'...for the defined ABI requirement (that I described two posts ago) plain function pointers would have to be used...
If the goal is to maintain a natural syntax, then the public interface needs to be used the same way as a natural class. Thus normal function table would not have enough information to deduce the 'this' pointer. The best compromise may be to use Don Clugston's Fast Delegate which is simply 2 pointers per entry. The this pointer would be 'redundant', but it would probably greatly accelerate invocation speed and enable a natural syntax. Don's delegate probably uses too many 'hacks' to be considered for ABI simplification.
>> 3) Global static mapping, in which case you would end up with something
>> like today's virtual functions where the 'inheritance' is calculated at
> If I understood you correctly, by this you mean the 'static vtable + vtable ptr' approach...?
> Anyways I'm for having the option of (2) (a contained struct of pointers/vtable) and (3)...If you want, as far as I am concerned, you can add (1) as an option however I must admit I do not see its usefulness...
I think the difference between the approaches is a matter of how easy it is to implement each method and how much boiler plate code we can eliminate for the user. The best code-it-by-hand solution is outlined in the boostcon 2010 presentation on type erasure (previously linked in this thread). The purpose of a library would be to reduce the amount of work required to achieve this.
>> Imagine being able to assign any two structs where the assignment operation
>> is defined as 'if they both have a field of the same name & convertible
>> type' then the fields are assigned, otherwise not. You could have different
>> policies such as "require all fields" or "optional fields". I suspect that
>> such a construct would make creating functions that take 'named parameters'
>> much easier.
> I'm not sure how this relates to a Boost.Interfaces library..?
Well it falls under the concept of mapping member variables vs member functions. Not polymorphic. This is actually a much easier problem than dealing with the methods.
> "What Huxley teaches is that in the age of advanced technology, spiritual
> devastation is more likely to come from an enemy with a smiling face than
> from one whose countenance exudes suspicion and hate."
> Neil Postman
> Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk