By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,107 Members | 1,174 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,107 IT Pros & Developers. It's quick & easy.

Constraining a template class argument to a derived class of base

P: n/a
Hello world,

I'm trying to figure out some way to constrain a template class
argument for a member function definition, such that the template
class argument must, totally, absolutely be a derived class of a
certain base class.

My current solution is:

class Base {
// etc..
};

class BaseHolder {
//etc
public:
template<class T>
T* make(void) {
/*This one!*/
Base* _check_derived_from_Base_ =
static_cast<Base*>((T*) 0);
return new(alloc(sizeof(T))) T();
}
};

It *seems* to work, but I think it's kind of hackish. Is there a
better, standards-defined way where I can specify that the class T in
the template should derive from "Base"?

Sincerely,
AmkG
Nov 5 '08 #1
Share this Question
Share on Google+
2 Replies


P: n/a
amkg wrote:
Hello world,

I'm trying to figure out some way to constrain a template class
argument for a member function definition, such that the template
class argument must, totally, absolutely be a derived class of a
certain base class.

My current solution is:

class Base {
// etc..
};

class BaseHolder {
//etc
public:
template<class T>
T* make(void) {
/*This one!*/
Base* _check_derived_from_Base_ =
static_cast<Base*>((T*) 0);
return new(alloc(sizeof(T))) T();
}
};

It *seems* to work, but I think it's kind of hackish. Is there a
better, standards-defined way where I can specify that the class T in
the template should derive from "Base"?
Look in the archives for 'boost::enable_if', there will probably be an
example of determining whether the class is a base class or a derived
class of 'T'... Not sure if it's going to become standard (it isn't)
but Boost libraries are widely used nowadays (and most are free, IIRC).

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Nov 5 '08 #2

P: n/a
On Nov 6, 12:09*am, Michael DOUBEZ <michael.dou...@free.frwrote:
amkg a écrit :
Hello world,
I'm trying to figure out some way to constrain a template class
argument for a member function definition, such that the template
class argument must, totally, absolutely be a derived class of a
certain base class.
My current solution is:
class Base {
// etc..
};
class BaseHolder {
//etc
public:
* * template<class T>
* * T* make(void) {
* * * * /*This one!*/
* * * * Base* _check_derived_from_Base_ =
* * * * * * static_cast<Base*>((T*) 0);
* * * * return new(alloc(sizeof(T))) T();
* * }
};
It *seems* to work, but I think it's kind of hackish. *Is there a
better, standards-defined way where I can specify that the class T in
the template should derive from "Base"?

Use boost static_assert and is_derived:
BOOST_STATIC_ASSERT(is_derived(T,Base));

If you don't want boost, the usual way to make the template
instantiation fail if a conversion cannot occur:

template <class T, class B>
struct assert_derived
{
* * *//declare static constant to avoid T default construtible
* * *static const T x;

* * *//convert type to its pointer
* * *template <class X>
* * * * *static X* to_pointer(X const&);

* * *//if can convert
* * *static char convert_to_base(B const*);

* * *//this fail if cannot convert to pointer
* * *static const bool test=sizeof(convert_to_base(to_pointer(x)));

};

Then in your code:
assert_derived<T,Base>();

But the error code generated if far from meaningful.

--
Michael
Thanks, I'll check out that template. Currently the hack I posted
gives a reasonable error in gcc - invalid static_cast from type ‘Bar*’
to type ‘Base*'. If the error code of that template is worse, I'll
stick with my hack I guess.
Nov 5 '08 #3

This discussion thread is closed

Replies have been disabled for this discussion.