|
Boost : |
From: MB (mb2act_at_[hidden])
Date: 2005-11-29 20:28:40
Hi,
This proposal is somewhat beyond the current Boost.Range.
I have been looking for "how to define compile-time polymorphism",
which Boost.Range and Boost.Serialization etc are combating.
Motivation:
There is no conforming way of customization if you cannot
open namespaces that contain types you customize.
New Implementation:
Provide a namespace for customization by using a type named 'overloaded'
that triggers intentional ADL on 2nd-phase lookup.
(This idea comes from Boost.Serialization.)
Snippet:
namespace boost { namespace range {
struct overloaded { }; // ADL trigger
// the metafunction
template< class T > // default
struct iterator
{
typedef typename T::iterator type;
};
// the begin
template< class T >
typename iterator<T>::type
begin(T& x)
{
// ADLookup to the same namespace as T or 'overloaded'.
return begin(x, overloaded());
}
// library-defined
template< class T > // default
typename iterator<T>::type
begin(T& x, overloaded)
{
return x.begin();
}
} } // namespace boost::range
namespace my {
template< class T >
typename boost::range::iterator<T>::type
algo(T& x)
{
// ...
return boost::range::begin(x);
}
}
namespace your {
template< class T1, class T2 >
struct pair
{
T1 first;
T2 second;
};
}
// user-defined
namespace boost { namespace range {
template< class Iterator >
struct iterator< your::pair<Iterator, Iterator> >
{
typedef Iterator type;
};
template< class Iterator>
Iterator begin(your::pair<Iterator, Iterator>& p, overloaded)
{
return p.first;
}
} } // namespace boost::range
int main()
{
std::string str;
boost::range::iterator<std::string>::type it1 = my::algo(str);
your::pair<char*,char*> pr;
boost::range::iterator< your::pair<char*,char*> >::type it2 = my::algo(pr);
return 0;
}
Result1:
In either case of metafunctions or functions, you open 'namespace boost::range'.
Result2:
You can avoid awkward names like 'boost_range_begin' that suppresses name-conflicts.
(Why not use types!)
Result3:
You may provide a special namespace for customizations named like 'overloadset',
where the type 'overloaded' is defined.
Result4:
Aside from Boost.Range, you can overload functions for built-in types, which have no
associated namespaces.
Result5:
Broken compilers that have no ADL can be handled without any burden to users.
(See: <boost/serialization/serialization.hpp>)
Question1:
I said on Motivation that there is "no" way.
Is it positive?
Do you know other workarounds? (though broken compilers can easily work around.)
Question2:
I said on Result2 that you can avoid the long names.
Is it positive? Any danger?
Question3:
What if we cannot open even 'namespace boost::range'?
If 'namespace range' becomes the member of 'namespace std', what can I do?
Can Result3 be the workaround?
Question4:
This technique that triggers intentional ADL is famous?
What do they call? Who is the inventor?
Should I call "Ramey Lookup"?
Question5:
Is 'overloaded' the appropriate name?
Should it be the first parameter of 'begin'?
Regards,
MB
http://p-stade.sourceforge.net/
--------------------------------------
STOP HIV/AIDS.
Yahoo! JAPAN Redribbon Campaign 2005
http://pr.mail.yahoo.co.jp/redribbon/
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk