Constraining a template class argument to a derived class of base

Discussion in 'C++' started by amkg, Nov 5, 2008.

  1. amkg

    amkg Guest

    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
     
    amkg, Nov 5, 2008
    #1
    1. Advertising

  2. Re: Constraining a template class argument to a derived class ofbase

    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
     
    Michael DOUBEZ, Nov 5, 2008
    #2
    1. Advertising

  3. amkg

    amkg Guest

    On Nov 6, 12:09 am, Michael DOUBEZ <> wrote:
    > 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.
     
    amkg, Nov 5, 2008
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.

Share This Page