【问题标题】:How to enforce child-of-X limitation on template parameter?如何对模板参数强制执行子 X 限制?
【发布时间】:2012-12-25 06:59:29
【问题描述】:

假设我想强制传入的模板参数是 Foo 的子参数。

有没有办法通过类型特征来强制执行这一点?编译时 static_assert 失败会很棒。

在下面的代码中,让我们把它变成一个两部分(单独)的问题。

  1. 只允许 My_Limited_Template<Bar> 编译。
  2. 只允许 My_Limited_Template<TBar> 编译。

编辑 对于错误的命名,我深表歉意:TBarTBaz 在目的上是非模板类。我只是在名称前附加了 T 以消除第 1 部分中的类的歧义。

代码

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
};

【问题讨论】:

  • 所以第二部分是"只允许使用CRTP从TFoo派生的参数"?
  • @jrok +1 如果您可以参与 CRTP,那就更好了,但我不确定这是否可能!
  • 我的意思是在导出TBar时使用了CRTP。这是您想要允许的唯一TFoo 孩子,还是可以拥有struct X : TFoo&lt;int&gt; { }; 之类的东西?
  • @jrok - 是的,我明白你的意思。我的意思是,我的初衷是强制执行 CRTP 要求,但由于我认为这根本不可能,所以我没有提及任何内容(暗示一个更宽松的要求:如struct X : TFoo&lt;int&gt; { } 很好)。
  • Leonid 的回答可以满足您的原始要求(使用 CRTP)。见here

标签: c++ templates c++11 typetraits


【解决方案1】:

我假设您在TBarTBas 的定义中犯了错误,请检查我的修改是否正确。

#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"
        ); 
};

【讨论】:

  • 我不认为你的第二部分是正确的(你为什么假设问题是错误的?)。 IIUC,问题要求TTFoo 的某些(未指定)实例化的子类,而您的答案要求T 是具体TFoo&lt;T&gt; 的子类。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-20
  • 2017-11-17
  • 1970-01-01
  • 2011-05-04
  • 2015-08-01
  • 1970-01-01
相关资源
最近更新 更多