C++描述了这个类的示例

sky*_*gle 13 c++ templates traits

我已经有一段时间没有使用C++的高级功能了,并且正在刷新我的C++知识.话虽如此,基于特征和策略编程的概念是我从未真正设法解决的问题.

我想改变这一点.我正在写一个通用容器.我想强制执行一个策略,即容器只存储从特定基类派生的类.这是因为当尝试访问向量边界外的项时,容器返回无效对象(而不是抛出).

template <class T>   
class GenericContainer
{
private:
    typedef std::vector<T> TypeVect;
    void addElement(const T& elem);

    TypeVect m_elems;

public:
    unsigned int size() const;
    T& elementAt(const unsigned int pos);
    const T elementAt(const unsigned int pos) const;
};
Run Code Online (Sandbox Code Playgroud)

我如何使用traits来限制这个泛型容器只包含类'ContainerItem'的子类?

Fre*_*abe 12

您可以使用一个IsDerivedFrom只能在给定类型"D"继承另一个类型"B"的情况下实例化的小模板(此实现取自一个很好的Guru Of The Week文章):

template<typename D, typename B>
class IsDerivedFrom
{
  static void Constraints(D* p)
  {
    B* pb = p; // this line only works if 'D' inherits 'B'
    pb = p; // suppress warnings about unused variables
  } 

protected:
  IsDerivedFrom() { void(*p)(D*) = Constraints; }
}; 

// Force it to fail in the case where B is void
template<typename D>
class IsDerivedFrom<D, void>
{
  IsDerivedFrom() { char* p = (int*)0; /* error */ }
};
Run Code Online (Sandbox Code Playgroud)

您现在可以IsDerivedFrom使用继承简单地实例化模板:

template <class T>   
class GenericContainer : public IsDerivedFrom<T, ContainerItem>
{
    ...
};
Run Code Online (Sandbox Code Playgroud)

此代码仅在T继承时编译ContainerItem.


Fle*_*exo 5

您可以使用boost :: mpl强制执行此操作,以便在编译时断言类型从基类继承.

"滚动你自己"非常简单:

template <typename D, typename B>
class is_derived_from {
   class No { };
   class Yes { No no[2]; };

   static Yes Test(B*);
   static No  Test(...);
public:
   enum { inherits = sizeof(Test(static_cast<D*>(0))) == sizeof(Yes) };
   static bool is_derived() { return inherits; }
};
Run Code Online (Sandbox Code Playgroud)

我认为这最初来自GoTW.您所需要的只是一个合适的断言机制(编译时间可能更好).通常的技巧是创建一个宏,使得一个负大小的数组使assert失败,或者1传递它.