Sign in to follow this  

template inheritance check

This topic is 4748 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Quote:
Original post by 0xCHAOS
*** Source Snippet Removed ***

what code could I add to C to enforce that T must derive from D?

If you have boost:


#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>

class D {};

template < typename T
, typename Enabler = void
>
class C;

template < typename T >
class C< T
, typename ::boost::enable_if< ::boost::is_base_and_derived< D
, T
>
>::type
>
{
/* your class definition goes here */
};


This will work for both public and non-public bases. It makes it so the definition is literally only defined if T derives from D. If you want to have it only work with public bases, use ::boost::is_convertible with a pointer to T and a pointer to D instead of ::boost::is_base_and_derived.

If your compiler isn't compliant with SFINAE, you can also use a BOOST_STATIC_ASSERT inside the class definition instead of selective partial specialization.

Share this post


Link to post
Share on other sites
Polymorphic_OOP - I'd probably use boost's static assertions instead of mucking with MPL:


#include <boost/static_assert.hpp>
#include <boost/type_traits.hpp>

class D {};

template<class T>
class C
{
// need two (()) because of the comma
BOOST_STATIC_ASSERT((::boost::is_base_and_derived<D,T>::value));

// your code here.
};




And I believe you meant Partial Template Specialization, not Substitution Failure Is Not An Error.

Share this post


Link to post
Share on other sites
Quote:
Original post by Fruny
Polymorphic_OOP - I'd probably use boost's static assertions instead of mucking with MPL

Actually, the code I provided doesn't even use mpl Fruny (though it uses the abstract concept of a bool metavalue). Even still, there is absolutely nothing wrong with it if I did use mpl in the example -- it's a beautiful library. The reason I only suggested static assertions as an alternative to enable_if is because, in my opinion, enable_if more clearly defines the situation. A selective specialization means, quite literally, that the type isn't defined when you pass those template parameters, whereas a static assertion means that the type is defined with error. Selective specialization also often gives a more concise error message.

Quote:
And I believe you meant Partial Template Specialization, not Substitution Failure Is Not An Error.

No, I meant SFINAE. That's how enable_if works. It will only partially specialize if the condition is met, since if the condition is false, substitution will fail.

Share this post


Link to post
Share on other sites
arg... I keep trying to post a message explaining a problem I'm still having, but it seems the forums get messed up for a few moments every time I do, so heres a link to the post I'm trying to make:

Share this post


Link to post
Share on other sites
Ah, so somebody did see that totally failed post before I deleted it [lol]. I was a bit tired and not thinking clearly and that version was totally flawed - it doesn't cover derived types at all. Instead I'll offer this:
class D {};

class F : public D{int i;};

class E {};

class True
{
char m;
};

class False
{
unsigned long m;
};

class NoType
{
};

struct Type
{
typedef bool result;
};

template <typename T>
True IsSame(T*, T*);

template <typename T, typename F>
False IsSame(T*, F*);

template <typename D, typename T>
struct DerivedFromImpl
{
static D d;
static T t;
static const bool result = sizeof(IsSame<D>(&d, &t)) == sizeof(True) || sizeof(IsSame<T>(&d, &t)) == sizeof(True);
};

template <bool Switch, typename R1, typename R2>
struct Select
{
};

template <typename R1, typename R2>
struct Select<true, R1, R2>
{
typedef R1 result;
};

template <typename R1, typename R2>
struct Select<false, R1, R2>
{
typedef R2 result;
};

template <typename D, typename T>
struct DerivedFrom
{
typedef typename Select<DerivedFromImpl<D, T>::result, Type, NoType>::result result2;
typedef typename result2::result result;
};

template < typename T >
class C
{
private:
typedef typename DerivedFrom<T, D>::result mustDeriveFromD;
};

int main()
{
C<D> ok;
C<F> ok2;
// C<E> fail;
}




I make no guarantee of its correctness or portability, but it seems to work on GCC, BCB and VC++. Most of the ideas are copied from the boost source, but I had to find workarounds for things that I still don't know why they didn't work - or even why boost does it that way in the first place!

Enigma

Share this post


Link to post
Share on other sites
I can't use that method because it creates static instances of both D and T, and these are singleton types. However, I just stumbled upon an amazingly simple solution: adding the line

SingletonBase * pb = s_inst;

in both the GetInst ( ) and AddDependency ( ) methods.

Anyhow, thanks for the help!

Share this post


Link to post
Share on other sites

This topic is 4748 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this