C++此类的特征示例

发布于 2024-10-14 01:10:18 字数 551 浏览 6 评论 0原文

我已经有一段时间没有使用 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;
};

我将如何使用特征来限制这个通用容器仅包含“ContainerItem”类的子类?

I haven't used the advanced features of C++ for a while and am refreshing my C++ knowledge..
Having said that, the concept of traits and policy based programming was something that I never really managed to get my head around.

I want to change that. I am writing a generic container. I want to enforce a policy that the container will store only classes that derive from a particular base class. This is because the container returns an invalid object (instead of throwing) when an attempt is made to access an item outside the vector bounds.

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

How would I use traits to restrict this generic container to contain only subclasses of class 'ContainerItem' say?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

折戟 2024-10-21 01:10:18

您可以使用一个小的 IsDerivedFrom 模板,该模板只能在给定类型“D”继承另一个类型“B”的情况下实例化(此实现取自 本周优秀大师文章):

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

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

template <class T>   
class GenericContainer : public IsDerivedFrom<T, ContainerItem>
{
    ...
};

仅当 T 继承 ContainerItem 时,此代码才会编译。

You can use a little IsDerivedFrom template which can only be instantiated in case a given type 'D' inherits another type 'B' (this implementation was taken from a nice Guru Of The Week article):

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

You can now simply instantiate the IsDerivedFrom template using inheritance:

template <class T>   
class GenericContainer : public IsDerivedFrom<T, ContainerItem>
{
    ...
};

This code only compiles if T inherits ContainerItem.

禾厶谷欠 2024-10-21 01:10:18

您可以使用 boost::mpl 在编译时断言类型继承自基类。

“roll your own”相当简单:

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

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

You can enforce this using boost::mpl to assert at compile time that a type inherits from a base.

The "roll your own" is fairly simple:

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

I think this came from GoTW originally. All you need then is a suitable assert mechanism (compile time is probably nicer). The usual trick to this is to create a macro that makes an array with negative size to fail the assert or 1 to pass it.

拧巴小姐 2024-10-21 01:10:18

我认为您正在寻找概念检查。这本来要内置到 C++0x 中,但已被推迟。 Boost 库包含一个用于管理概念的库,但它远非语法糖果。

旁注:小心容器中的对象切片。如果您希望允许基类和派生类都存储在容器中,请使用指针而不是对象本身。

I think you are looking for concept checking. This was about to be built in to C++0x but it has been postponed. The Boost libraries contain a library for managing concepts but it's far from being a syntax candy.

Side note: Be careful about object slicing in your container. In case you want to allow both base and derived classes to be stored in the container, use pointers instead of the objects itself.

梦里寻她 2024-10-21 01:10:18

类型特征和基于策略的编程是不同的主题。类型特征添加有关现有类型和不能包含额外信息(任何内置)的类型的新信息。基于策略的设计是一种设计类的方法,以便您可以以各种方式组装它们来创建不同的行为;这是一种编译时状态模式。

Type traits and policy based programming are distinct topics. Type traits add new information about existing types and types that can't contain extra information (any builtin). Policy based design is a method of designing classes so that you can assemble them in various ways to create different behaviors; it's sort of a compile-time state pattern.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文