|
Boost : |
From: Alexander Nasonov (alnsn-mycop_at_[hidden])
Date: 2003-05-07 04:26:29
Lin Xu wrote:
> I have just been reading about dynamic any. As far as I can tell, it
> allows the user to implement an interface to extend an any, so one can
> call functions and access the internal value of the any without knowing
> the type.
>
> I think this is a very good idea, but I'm not sure how complex adding new
> 'functions' / 'interfaces' is. It seems to me (seeing the new io_any) that
> is looks like you need to define a class that inherits from the template
> that takes a fuction type as the parameter.
Yes, this is well-known technique known as curiously recurring template
pattern. I don't see any difficulties here. The rule is extermely simple
and it takes a second to follow it.
Reference: James O. Coplien. "Curiously Recurring Template Patterns," C++
Report, February 1995
> Then AFAIK (I coudl be wrong
> here, probably am) the any template uses that...
I don't understand the end of the sentence.
> First of all, are function calls supported?
What kind of calls? There are actually two:
1) Call of every operation (you call it addon) is supported in a natural
way. It means that the operation has function-call operator implemented
(one reason to use curiously recurring template pattern). You can see
reader and writer calls in io_any example.
2) There is function_call operation defined in operations.hpp. If *any*
supports it then the *any* itself becomes callable, that is, everything
that it holds should be callable and *any* redirect arguments of
function-call operator to the held functional-value. In this case *any* is
a variant of Boost.Function.
> I can't see anything like that
> and the documentation isn't completed. I'm not sure because I dont'
> understand how you are distugishing between each 'function' addon (like
> writer, and reader, or adder and subtracter)
I don't understand what do you mean by "distinguish".
> I implemented a similar class, but using what appears to be a totally
> different implementation method. I'm not sure if I shoudl continue to
> develop it (I'm trying to allow casts between any_interface aka a
> dynamic_any - which allows virtual templates ;) and other cool stuff.
> There
> is always a trade off though, either register the interface or the type
> held..so I'm trying other techniques. )
> Here is an useage example..
>
> struct printable {
> struct intf {
> virtual void print(ostream& out) = 0;
> friend ostream& operator<<(ostream& out,intf& val) {
> val.print(out);
> };
> template <class parent> struct impl : public parent {
> virtual void print(ostream& out) {
> out << value();
> }
> };
> };
Is it simpler then mine writer operation?
struct writer
: boost::dynamic_any::function
<
writer, // curiously recurring template pattern
std::ostream & (std::ostream &, const anyT &)
>
{
template<class T>
std::ostream & call(std::ostream & out, const T & obj) const
{
return out << obj;
}
};
> any_interface<printable> a;
> a = 10;
> cout << *a << endl;
> a = "hi, I'm a string";
> cout << *a << endl;
>
> This to me seems clearer and also allows functions and so on, for
> example..
> (Of course the current implementation probably does, but I coudlnt' find
> any documentation to that effect.) The syntax useage is similar to an
> iterator: -> gets the interface as a pointer, * as an &.
>
> any_interface<moveable> a;
> a->move(10,10);
> //or
> (*a).move(10,10);
dynamic_any dosn't give you access to the interface in this way because you
can have as many interfaces as you wish. There is a different way:
move()(a, 10, 10);
where move is:
struct move
: boost::dynamic_any::function
<
move, // curiously recurring template pattern
void (anyT &, int, int)
>
{
template<class T>
void call(T & obj, int x, int y) const
{
obj.move(x, y);
}
};
>
> As well, it works on VC6 even. (I'm not sure if the current implement
> does, but considering it looks like it wants to distugish a function
> template paramter....)
>
> My implementation provides the same as the current one, just rename
> any_interface to dynamic_any.
> I'm wondering if my implementation has some serious problem I'm not
> seeing?
One problem that I see right now is a single interface bottleneck.
> The cost is a virtual function call per function call.
Well, for functions with one *any* argument it's also one virtual function
call plus copying of arguments references to build an arguments tuple.
-- Alexander Nasonov Remove minus and all between minus and at from my e-mail for timely response
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk