Boost logo

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