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
struct non_const_member_base
{
typedef Type result_type;
template<typename ChainedPtr>
#if !defined(BOOST_NO_SFINAE)
typename disable_if<
is_convertible,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