Composing a set of container classes and accessing them from a base
I'm trying to use boost::mpl::inherit_linearly
to compose a container class using types provided by the user:
#include <typeinfo>
#include <iostream>
#include <vector>
#include <boost/mpl/inherit.hpp>
#include <boost/mpl/inherit_linearly.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/vector.hpp>
namespace mpl = ::boost::mpl;
//////////////////////////////////////////////
// Create the container by chaining vectors
//////////////////////////////////////////////
struct Base {};
// Types provided by the user
typedef mpl::vector<int, char, double>::type myTypes;
typedef mpl::inherit_linearly<
myTypes,
mpl::inherit<mpl::_1, std::vector<mpl::_2> >,
Base
>::type InheritedContainer;
// Function for accessing containers
template <typename T>
inline std::vector<T>& get_container(Base& c) {
return static_cast<std::vector<T>& >(c);
}
// Some functions that manipulate the containers
// NB: These functions only know about the Base and the types
// they want to access
void my_int_func(Base& b) {
get_container<int>(b).push_back(42);
}
void my_char_func(Base& b) {
get_container<char>(b).push_back('c');
}
int main() {
InheritedContainer container;
Base& bref = container;
my_int_func(bref);
std::cout << "Int: " << get_container<int>(bref).back() << std::endl;
my_char_func(bref);
std::cout << "Char: " << get_container<char>(bref).back() << std::endl;
return 0;
}
The compile error I get is:
question.cpp:开发者_开发百科 In function ‘std::vector<T, std::allocator<_CharT> >& get_container(Base&) [with T = int]’:
question.cpp:40: instantiated from here
question.cpp:31: error: invalid static_cast from type ‘Base’ to type ‘std::vector<int, std::allocator<int> >&’
question.cpp: In function ‘std::vector<T, std::allocator<_CharT> >& get_container(Base&) [with T = char]’:
question.cpp:44: instantiated from here
question.cpp:31: error: invalid static_cast from type ‘Base’ to type ‘std::vector<char, std::allocator<char> >&’
Shouldn't Base
be a base of whatever type is produced by inherit_linearly
? And if so, shouldn't a vector<int>
and the other vectors show up in the type hierarchy for static_cast to pull out?
Is there any other way to get this functionality?
I think Base
is a base class of InheritedContainer
, but not of
std::vector<int>
.
As we know, std::vector
isn't defined as the following:
class vector : Base {...
You may expect the following inheritance:
class InheritedContainer : Base, std::vector<int>, ... {...
However, in this case, the cast from Base
to vector<int>
is a cross-cast,
so this cannot be done with static_cast
.
As you may know, the following is allowed:
InheritedContainer container;
Base& bref = container;
InheritedContainer& iref = static_cast<InheritedContainer&>(bref);
std::vector<int>& vi = iref;
std::vector<char>& vc = iref;
If you can prepare get_container
, my_int_func
and my_char_func
, probably the types
to which the std::vector
will be specialized are known beforehand.
If so, I suppose it is pertinent to hold InheritedContainer&
instead of Base&
all along.
If you have to cast Base
to vector<T>
, probably
RTTI(for example adding virtual function to Base
) and dynamic_cast
will enable
the cast.
精彩评论