Boost logo

Boost Users :

Subject: [Boost-users] [MultiIndex] more on key extractor issues
From: John M. Dlugosz (mpbecey7gu_at_[hidden])
Date: 2013-01-18 00:36:41


I think my problem stems from the use of 'const' in the underlying element with pointer
traversal.

Consider:

typedef multi_index_container<
     shared_ptr< const ItemBase >,
     indexed_by<

        ordered_non_unique<
           member<
              const ItemBase, // <<--- here
              const unsigned long, // <<--- here
              &ItemBase::some_member
>
>, // ordered_non_unique

        ordered_unique<
           tag<S2>,
           member<
              ItemBase,
              const S2,
              &ItemBase::another_member
>
> // ordered_unique

> // indexed_by
> ItemList_type_base;

I added the two 'const' occurrences on the lines marked with "here", and it behaved
better. I think it worked with the second index originally because one of those const's
was originally there. The member in question was originally const, so I had included
const as part of the type there.

Basically, what is happening on Windows VS10 is:

template<class Class,typename Type,Type Class::*PtrToMember>
struct non_const_member_base
{
   typedef Type result_type;

   template<typename ChainedPtr>

#if !defined(BOOST_NO_SFINAE)
   typename disable_if<
     is_convertible<const ChainedPtr&,const Class&>,Type&>::type
#else
   Type&
#endif

   operator()(const ChainedPtr& x)const
   {
     return operator()(*x); // <<-- HERE
   }

   const Type& operator()(const Class& x,int=0)const
   {
     return x.*PtrToMember;
   }

   Type& operator()(Class& x)const
   {
     return x.*PtrToMember;
   }

};

The ChainedPointer form unpeels a const-qualified type with (*x), and that matches the
middle form, not the third. But the signature on the first form is looking for Type,
which is exactly what I put in the member<...> index directive.

So, I suggest that a quick note concerning constant types inside chained pointer following
could be added to the tutorial section.

Meanwhile, a stranger problem occured on the Mac, using the Clang compiler.

I got an error saying that none of the operator() candidates were viable for overloading,
with the error indicating that the type of thing being passed in was the shared_ptr<const
ItemBase>. It said the first form was ignored because of instantiation failure, but that
is exactly contrary to the disable_if. I'm suspecting that the is_convertable itself
somehow choked rather than producing false_type...? Naturally none of the other overloads
matched, as a shared_ptr<T> cannot be passed where a T is expected, and that's exactly
when the first form would be switched in!

—John


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net