【问题标题】:call methods of type parameter from methods of templated class (C++)从模板类的方法调用类型参数的方法(C++)
【发布时间】:2015-02-25 05:13:30
【问题描述】:

我正在尝试使用模板在 C++ 中实现 HashMap(同时了解模板的工作原理)。为此,我需要从参数类型T 调用方法T :: equals()

这是我需要的简化代码:

template < class T > class Map{
    public:
    T* [] cells;
    replaceIfEquals( int index,  T a ){
        if( cells[index].equals( a );  ) cells[index] = a;
    };
};

假设T 应该是这样的

class Point2D : public Comparable {
    public:
    virtual bool equals( Object o ){    Point2D p = (Point2D)o;     return ( ix == p.ix ) && ( iy == p.iy );    };
};

它是一些更通用类型的子类型(在 Java 中我会使用接口)

class Comparable {
    public:
    virtual bool equals( Object o ){ return false; };
};

我想我在模板的概念中遗漏了一些非常基本的东西。

【问题讨论】:

  • T 可以是任何类,但并非所有类都有方法 T.equals( Object o )。那么编译器怎么知道我以后只会使用Comparable类型的类呢?
  • 编译器只知道何时尝试使用特定 T 实例化模板并检查该 T 是否具有适当的成员函数。

标签: c++ templates inheritance hashmap


【解决方案1】:

如果为T 定义了operator==,您可以创建一个特征is_comparable&lt;T&gt; 返回真或假。然后你可以使用static_assert 在你的Map 类中创建一个编译时断言:

template<class T, class = void>
struct is_comparable
    : std::false_type { };

template<class T>
struct is_comparable<T, decltype(void(std::declval<T>() == std::declval<T>()))>
    : std::true_type { };

template<class T>
class Map
{
    // ...
    static_assert(is_comparable<T>::value, "T must be comparable");
};

如果您传递Map 一个未定义operator== 的类型,您将收到带有自定义消息的编译错误。就像 Michael 说的,这就是你在 C++ 中的做法。

【讨论】:

    【解决方案2】:

    在 C++ 中忘记“对象”或继承的“等于”。那是Java主义。在 C++ 中,我们这样做:

     class Point2D {
       public:
         // ...
         bool operator==(const Point2D& other) const;
         // ...
     };
    

    在您的地图代码中,您可以简单地使用x == y 而不是x.equals(y)。请注意,您的地图当前有一个指针列表,因此您需要取消引用他的指针来执行该操作(也就是说,您需要执行 *xPtr == *yPtr 来比较指向的值而不是地址。

    【讨论】:

    • 好的,但是应该是一样的——编译器怎么知道运算符==是为所有可能的参数T定义的?
    • @ProkopHapala 这就是模板与继承的不同之处。使用模板时,编译器会验证模板是否使用提供模板使用的所有函数的类型进行实例化。因此,您根本不需要继承关系。
    猜你喜欢
    • 2011-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多