Boost logo

Boost Users :

From: Ovanes Markarian (om_boost_at_[hidden])
Date: 2007-03-28 05:14:42


On Wed, March 28, 2007 02:57, Scott Meyers wrote:
> Given some base class,
>
> class Base { virtual ~Base(){} };
>
> I want to be able to implement this:
>
> template<typename Seq>
> const Base& createObject()
> {
> // return an object that inherits from Base and every type in Seq
> }
>
> The problem is how to create the type of object I want.
>
> mpl::inherit is almost what I need, but it takes as template parameters each
> type to inherit from, and I don't have discrete types, I have a sequence of
> types. mpl::inherit_linearly takes a sequence and would work for my purposes
> (which is to create an object that I can later check via dynamic_cast to see if
> it inherits from a given type), but it works only with forward sequences, and
> I'll typically have an mpl::set. I could copy the contents of Seq into an
> mpl::vector and go from there, but that seems kind of gross.
>
> Is there a good way to solve this problem that I am overlooking?
>
> Thanks,
>
> Scott
>

Scott,

I still think inherit_lineraly is what you need. mpl::set is also a Forward Sequence. The doc for
Forward Sequence states:

http://www.boost.org/libs/mpl/doc/refmanual/forward-sequence.html

A Forward Sequence is an MPL concept representing a compile-time sequence of elements. Sequence
elements are types, and are accessible through Iterators. The begin and end metafunctions provide
iterators delimiting the range of the sequence elements. A sequence guarantees that its elements
are arranged in a definite, but possibly unspecified, order. !!!Every MPL sequence is a Forward
Sequence.!!!

In the forward sequence docs is also defined:

For any Forward Sequence s the following expressions must be valid:
Expression Type Complexity
begin<s>::type Forward Iterator Amortized constant time
end<s>::type Forward Iterator Amortized constant time
size<s>::type Integral Constant Unspecified
empty<s>::type Boolean Integral Constant Constant time
front<s>::type Any type Amortized constant time

As I can see all these expressions are valid for mpl::set, so you can use inherit_linearly. The
only thing I would take care of, is to skip some fundamental types if these are possible in your
set (this can be done by using the combination of type_traits::is_scalar, mpl::filter_view,
mpl::inherit and mpl::inherit_linearly)

You can fine tune the is_scalar to identify type which can not be base...

Here the tested example with MSVC 8.0 Express Edition:

#include <boost/mpl/set.hpp>
#include <boost/mpl/filter_view.hpp>
#include <boost/mpl/inherit.hpp>
#include <boost/mpl/inherit_linearly.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/type_traits/is_scalar.hpp>

namespace bb = boost::bimap;
namespace mpl = boost::mpl;

struct A
{
        int get()const
        {
                return a_;
        }

        int a_;
};

struct B
{
        int get()const
        {
                return b_;
        }

        int b_;
};

struct C
{
        double get()const
        {
                return c_;
        }

        double c_;
};

typedef mpl::set<A, B, bool, double, int(*)(), C> mixed_set;

typedef mpl::inherit_linearly
        <
                mpl::filter_view< mixed_set, mpl::not_< boost::is_scalar<mpl::_> > >
        , mpl::inherit
                <
                        mpl::_1
                , mpl::_2
>
>::type inherited_type;

template<class T, class Res_>
Res_ call_get(T const& t)
{
        return t.get();
}

int main()
{
        inherited_type t;

        call_get<A, int>(t);
        call_get<C, double>(t);

        return 0;
}

With Kind Regards,

Ovanes Markarian


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