开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜