在Java中,你可以定义泛型类,它只接受你选择的扩展类的类型,例如:

public class ObservableList<T extends List> {
  ...
}

这是使用“extends”关键字完成的。

在c++中是否有与此关键字简单等价的东西?


当前回答

没有用于此类类型检查的关键字,但你可以放入一些至少会以有序方式失败的代码:

(1)如果你想让一个函数模板只接受某个基类X的参数,将它赋给函数中的X引用。 (2)如果你想接受函数但不接受原语,反之亦然,或者你想用其他方式过滤类,在你的函数中调用一个(空的)模板帮助函数,它只为你想接受的类定义。

你也可以在一个类的成员函数中使用(1)和(2)对整个类强制进行这些类型检查。

你可以把它放到一些智能宏来减轻你的痛苦。:)

其他回答

好吧,你可以这样创建你的模板:

template<typename T>
class ObservableList {
  std::list<T> contained_data;
};

然而,这将使限制成为隐式的,而且您不能只提供任何看起来像列表的东西。还有其他方法来限制所使用的容器类型,例如使用特定的迭代器类型,这些迭代器类型并不存在于所有容器中,但同样,这是一种隐式限制而不是显式限制。

据我所知,目前的标准中不存在完全镜像Java语句的结构。

有一些方法可以通过在模板中使用特定的typedefs来限制在模板中使用的类型。这将确保模板专门化的编译不包括特定的类型定义将失败,所以你可以有选择地支持/不支持某些类型。

在c++ 11中,概念的引入会让这变得更容易,但我不认为它会完全满足你的需求。

只接受类型List派生的类型T的等效函数如下所示

template<typename T, 
         typename std::enable_if<std::is_base_of<List, T>::value>::type* = nullptr>
class ObservableList
{
    // ...
};

在c++中是否有与此关键字简单等价的东西?

No.

根据你想要实现的目标,可能会有足够的(甚至更好的)替代品。

我已经看了一些STL代码(在linux上,我认为它是从SGI的实现派生出来的)。它有“概念断言”;例如,如果您需要一个能够理解*x和++x的类型,则概念断言将在一个什么都不做的函数(或类似的东西)中包含该代码。它确实需要一些开销,所以把它放在一个定义依赖于#ifdef debug的宏中可能是聪明的。

如果子类关系确实是你想知道的,你可以在构造函数中断言T instanceof list(除非它在c++中“拼写”不同)。这样,你就可以通过测试来避免编译器无法为你检查它。

我们可以使用std::is_base_of和std::enable_if: (static_assert可以被删除,如果不能引用type_traits,上面的类可以自定义实现或从boost中使用)

#include <type_traits>
#include <list>

class Base {};
class Derived: public Base {};

#if 0   // wrapper
template <class T> class MyClass /* where T:Base */ {
private:
    static_assert(std::is_base_of<Base, T>::value, "T is not derived from Base");
    typename std::enable_if<std::is_base_of<Base, T>::value, T>::type inner;
};
#elif 0 // base class
template <class T> class MyClass: /* where T:Base */
    protected std::enable_if<std::is_base_of<Base, T>::value, T>::type {
private:
    static_assert(std::is_base_of<Base, T>::value, "T is not derived from Base");
};
#elif 1 // list-of
template <class T> class MyClass /* where T:list<Base> */ {
    static_assert(std::is_base_of<Base, typename T::value_type>::value , "T::value_type is not derived from Base");
    typedef typename std::enable_if<std::is_base_of<Base, typename T::value_type>::value, T>::type base; 
    typedef typename std::enable_if<std::is_base_of<Base, typename T::value_type>::value, T>::type::value_type value_type;

};
#endif

int main() {
#if 0   // wrapper or base-class
    MyClass<Derived> derived;
    MyClass<Base> base;
//  error:
    MyClass<int> wrong;
#elif 1 // list-of
    MyClass<std::list<Derived>> derived;
    MyClass<std::list<Base>> base;
//  error:
    MyClass<std::list<int>> wrong;
#endif
//  all of the static_asserts if not commented out
//  or "error: no type named ‘type’ in ‘struct std::enable_if<false, ...>’ pointing to:
//  1. inner
//  2. MyClass
//  3. base + value_type
}

没有用于此类类型检查的关键字,但你可以放入一些至少会以有序方式失败的代码:

(1)如果你想让一个函数模板只接受某个基类X的参数,将它赋给函数中的X引用。 (2)如果你想接受函数但不接受原语,反之亦然,或者你想用其他方式过滤类,在你的函数中调用一个(空的)模板帮助函数,它只为你想接受的类定义。

你也可以在一个类的成员函数中使用(1)和(2)对整个类强制进行这些类型检查。

你可以把它放到一些智能宏来减轻你的痛苦。:)