Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to enforce child-of-X limitation on template parameter?

Suppose I want to enforce the limitation that the template parameter passed in is a child of Foo.

Is there a way to enforce this through type-traits? A compile-time static_assert failure would be great.

In the code below, let's make it a two-part (separate) question.

  1. Allow only My_Limited_Template<Bar> to compile.
  2. Allow only My_Limited_Template<TBar> to compile.

EDIT I apologize for the bad naming: TBar and TBaz are meant to be non-template classes on purposes. I just attached T in front of the names to disambiguate from the classes in Part 1.

CODE

struct Foo { };                // no
struct Bar : public Foo { };   // yes
struct Baz { };                // no

template< typename T >
struct TFoo { };                       // no
struct TBar : public TFoo<TBar> { };   // yes
struct TBaz { };                       // no

template< typename T >
struct My_Limited_Template
{
  // Part One:
  //   My_Limited_Template<Foo>  // disallow
  //   My_Limited_Template<Bar>  // allow
  //   My_Limited_Template<Baz>  // disallow
  // 
  // Part Two:
  //   My_Limited_Template<TFoo<int>> // disallow
  //   My_Limited_Template<TBar>      // allow
  //   My_Limited_Template<TBaz>      // disallow
};
like image 317
kfmfe04 Avatar asked Dec 25 '12 06:12

kfmfe04


1 Answers

I assume that you made an error in definition of TBar and TBas, check that my modification is correct.

#include <type_traits>    

struct Foo { };                // don't allow this
struct Bar : public Foo { };   // allow this
struct Baz { };                // don't allow this

template< typename T > struct TFoo { };                       
template< typename T > struct TBar : public TFoo<TBar<T>> { }; 
template< typename T > struct TBaz { };                       

template< typename T >
struct My_Limited_Template
{
        static_assert(
                (std::is_base_of<Foo,T>::value && !std::is_same<T,Foo>::value)
                || 
                (std::is_base_of<TFoo<T>,T>::value && !std::is_same<T,TFoo<T>>::value),
                "fail2"
        ); 
};
like image 70
Leonid Volnitsky Avatar answered Oct 13 '22 00:10

Leonid Volnitsky