Hello Matt,
----- Mensaje original -----
De: Matt Steele
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
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