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