$include_dir="/home/hyper-archives/boost-users/include"; include("$include_dir/msg-header.inc") ?>
From: JOAQUIN LOPEZ MU?Z (joaquin_at_[hidden])
Date: 2005-12-31 12:27:23
Hello Matt,
----- Mensaje original -----
De: Matt Steele <steelerm_at_[hidden]>
Fecha: Sábado, Diciembre 31, 2005 8:21 am
Asunto: [Boost-users] [multi_index] const_mem_fun with an inherited 
memberfunction
> I am trying to use Boost.Multi-index (version 1.33.0) to store a 
> set of
> boost::tuples, and it appears that const_mem_fun has some 
difficulties
> when the desired member function is inherited from a base class. The
> following typedef
> 
>  typedef multi_index_container<
>    tuple<int>,
>    indexed_by< ordered_non_unique< const_mem_fun< tuple<int>,
>                                                   const int&,
>                                                   &tuple<int>::get<0>
>                                                 >
>              >
>    >
>  > my_tuple_container_type;
> 
> yields this error (edited for clarity) on my compiler (g++ 4.0.3):
> 
>  &TupleBaseClass<int>::get' is not a valid template argument for 
> type 
>  'const int& (tuple<int>::*)()const' because it is of type 
>  'const int& (TupleBaseClass<int>::*)const'
>  note: standard conversions are not allowed in this context
> 
> 
> Now the declaration of boost::tuple has something like this:
> 
> template <class T>
> class tuple : public TupleBaseClass<T> {
> public:
>  typedef typename TupleBaseClass<T> inherited;
> ...
> };
> 
> (Also, as far as I can tell, get<0>() is declared and implemented in
> TupleBaseClass, not tuple).  The public typedef 'inherited' looked
> promising, so I modified my code as follows:
> 
>  typedef multi_index_container<
>    tuple<int>,
>    indexed_by< ordered_non_unique< const_mem_fun< 
> tuple<int>::inherited,                                             
>      const int&,
>                                                   &tuple<int>::get<0>
>                                                 >
>              >
>    >
>  > my_tuple_container_type;
> 
> and that compiles.
> 
> I have a few questions/comments about all this.  First of all, is my
> compiler correct to generate the error for the first case?  
Unfortunately, it is correct. There are some quirks
about the contravariance rules of pointer to members
in C++. For instance, the following is legal (as expected):
struct A
{
  int x;
};
struct B:A{};
int main()
{
  int B::* p=&B::x;
}
whereas the following is not:
struct A
{
  int x;
};
struct B:A{};
template<int B::*Ptr>
struct foo{};
int main()
{
  // error: argument of type "int A::*" is incompatible with
  // template parameter of type "int B::*"
  foo<&B::x> f;
}
To me, this is a defect in the standard, but there might
be a reason for this behavior. I'll go ask in comp.std.c++.
> Secondly, is
> the above workaround satisfactory?  My opinion is that it's a little
> ungainly; it appears to me that boost::tuple is a derived type for
> implementation reasons, and I'd rather not have to know about that 
> fact.
It is unsatisfactory for two reasons:
1. As you say, having to expose an implementation artifact is
ugly.
2. I think that the code won't work as expected: const_mem_fun
has some overloads of operator() in order to support
chained pointers (http://tinyurl.com/9cd2v) that will hide
the implicit conversion from const tuple<int>& to
const tuple<int>::inherited&. Could you please try to insert
some element in my_tuple_container_type? My hunch is that
you'll get a compiler error about tuple<int> not having
operator*. Please report back.
As for issue #2, I've corrected the problem (for SFINAE-capable
compilers) for the next Boost 1.34 release. Even so, issue #1
remains. My suggestion is that you simply provide a user-defined
key extractor like this (uncompiled, beware typos):
template<typename Tuple,int N>
struct tuple_member_extractor
{
  typedef typename 
    boost::tuples::element<N,Tuple>::type result_type;
  const result_type& operator()(const Tuple& t)const
  {
    return boost::tuples::get<N>(t);
  }
};
Hope this helps; I'd appreciate if you reported on the
success/failure of this approach.
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo