【问题标题】:C++ - Cannot compare const and non-const template types using operator overloadC++ - 无法使用运算符重载比较 const 和非 const 模板类型
【发布时间】:2015-07-12 12:58:11
【问题描述】:

我是 Stack Overflow 和 C++ 的新手!那么问题来了:

目标是使用下一个接口创建容器类:

IContainer.h:

class ElemNotFound {};

template < class ElemType, class IndexType > class IContainer
{
public:
    virtual const ElemType& GetElem(const IndexType& index) const throw (ElemNotFound) = 0;
    virtual void PutElem(const IndexType& index, const ElemType& elem) throw () = 0;
};

当前使用该接口的代码是:

    #include "IContainer.h"
    #include <vector>

    class Container : public IContainer < class ElemType, class IndexType >
    {

    private:

        struct ContainerElement
        {
            IndexType& Index;
            ElemType& Data;
        };

        std::vector < ContainerElement > MyVector;
        std::vector < ContainerElement > ::iterator MyIterator;

    public:

        // EDIT: that operator== part is incorrect as
        // failed attempt to circumvent inability to compare custom types
        friend bool operator== (IndexType& x, const IndexType& y)
        {
            if (x == y) return 1;
            else return 0;
        }

        const ElemType& GetElem(const IndexType& index)
        {
            try
            {

                MyIterator = MyVector.begin();
                while (MyIterator != MyVector.end())            

                {
                    if (MyIterator->Index == index)
                    // PROBLEM: missing operator "==" for IndexType == const IndexType
                    {
                        // do useful things
                    }
                    MyIterator++;
                }
            }

            catch (Exception e) // everything down below is a placeholder
            {
                throw (ElemNotFound) = 0;
            }
        }

        void PutElem(const IndexType& index, const ElemType& elem)
        {

        }
    };

IndexType 和 const IndexType 的直接比较(使用“==”)不起作用,原因我不知道。我想比较我的向量中的自定义索引和我在函数中使用的索引以从容器中获取元素。对自定义类型使用运算符重载“==”也不起作用。应该是不正确的继承还是不正确地使用运算符重载 - 我不知道!

那么问题来了:如何比较使用模板的类中的 const 和非 const 自定义类型变量?

【问题讨论】:

  • 您的operator== 函数是否有理由不通过常量引用获取both 参数?无论如何,运算符函数中的比较不会递归调用自身吗?
  • Joachim,那部分代码只是为了规避无法直接编写(MyIterator-&gt;Index == index) 的尝试。我知道这是不正确的 - 错误仍然存​​在。为什么我不能比较自定义类型和 const 自定义类型 - 我不知道。在 C++ 标准描述和 C++ 文献中也找不到答案。
  • ElemTypeIndexType 定义在哪里?
  • @SergeiBorodin 非 const 类型隐式转换为 const 类型。只需比较两个 const 类型
  • 不应该 operator== 比较两个 const Container&amp; 而不是 IndexTypes?

标签: c++ templates comparison constants operator-keyword


【解决方案1】:

您的代码存在根本问题;您看到的所有其他错误只会隐藏真正的错误。就是这一行:

class Container : public IContainer < class ElemType, class IndexType >

class ElemTypeclass IndexType 参数具有误导性。这些实际上是从未定义的类的前向声明。它们的名称与IContainer模板参数名称完全相同,这只是巧合。

换句话说:您正在使用不完整的类来实例化您的模板。

这意味着编译器对它们几乎一无所知。他们有公共构造函数吗?他们甚至支持operator==吗?

考虑一下这个极其简化的程序版本:

template < class ElemType, class IndexType > class IContainer
{
public:
    virtual void PutElem(const IndexType& index, const ElemType& elem);
};

class Container : public IContainer < class ElemType, class IndexType >
{
public:
    void PutElem(const IndexType& index, const ElemType& elem)
    {
        bool b1 = index == index;
        bool b2 = elem == elem;
    }
};

int main()
{
    Container c;
}

编译错误(取决于您的编译器):

stackoverflow.cpp(12) : error C2676: binary '==' : 'const IndexType' does not define this operator or a conversion to a type acceptable to the predefined operator
stackoverflow.cpp(13) : error C2676: binary '==' : 'const ElemType' does not define this operator or a conversion to a type acceptable to the predefined operator

你有它:类是未定义的,编译器甚至不知道它们是否支持==


其他问题:

  • ContainerGetElem 显然应该覆盖基类中的GetElem,但它在那里是const。覆盖区分const 和非const
  • MyIterator = MyVector.begin(); 行在 const 函数中不起作用,因为 MyIterator 已修改(而不是 mutable)。
  • 您的模板不适用于像 int 这样的原始类型,因为如果两个操作数都是原始类型,您就不能重载 operator==

我不完全确定您的代码的真正意图是什么,但也许您希望 Container 也成为一个模板,用于生成 Container 类?

你可以这样做:

template < class ElemType, class IndexType >
class Container : public IContainer < ElemType, IndexType >

这是起点;然后,您可以单独修复所有其他错误。随时为他们提出个别问题。

【讨论】:

  • 谢谢您,先生,您的广泛回答!确实,我遇到了问题,在定义模板类时遇到了根本问题。只要我不需要它并且一切正常,我就摆脱了operator==。其他小建议也非常有帮助。给我上了一课。
  • @SergeiBorodin:不客气 :) 当我们这样做时,您应该摆脱异常规范(例如函数声明的 throw (ElemNotFound) 部分)。它们从未得到所有主要编译器的完全支持,并且由于技术和语义原因,它们通常非常无用,单个评论无法详细解释。事实上,异常规范在现代版本的 C++ 中已弃用,唯一有用的变体 throw() 表示 no 抛出异常,已被 @987654347 取代@.
  • @SergeiBorodin:从std::exception 直接或间接派生自定义异常是一种很好的做法。
  • 再次感谢您:) 我已经进入了这个问题,因为标头是旧代码的一部分(正如您在 C++11 中提到的 noexcept),这不是我的和 throw (ElemNotFound) = 0 throw () = 0; 在我看来是很不寻常的。我是 C++ 新手(虽然我知道 C99),但在方法声明中使用赋值对我来说很奇怪。并感谢您 std::exception 的注意 - 点。
  • @SergeiBorodin:这些不是赋值,而是 C++ 将函数标记为纯虚拟的方式(就像 Java 中的抽象方法)。 AFAIK 曾经选择有趣的语法以避免向语言添加新关键字。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多