“多个运算符“!=”与这些操作数匹配”错误未停止编译?

问题描述 投票:0回答:1

所以我有一个模板类

TargetVar
,它本质上只是另一个变量的包装器,这样我就可以为所述变量设置目标值以及达到该值需要多少帧。每一帧,我都会在每个
TargetVar
上调用一个处理函数,将其值移向目标值。

这是课程:

class BaseTargetVar {
public:
    BaseTargetVar() {
        TargetVarManager::get_instance()->register_target_var(this); //TargetVarManager just iterates 
        //through all registered TargetVars and calls their process funcs
    }
    virtual ~BaseTargetVar() {
        TargetVarManager::get_instance()->unregister_target_var(this);
    }

    virtual void process() {}
};

template <class T> class TargetVar : public BaseTargetVar {
public:
    TargetVar() = default;


    TargetVar(T& other) {
        if (val != other) {
            val = other;
            frames = 0;
        }
    }
    
    TargetVar(const T& other) {
        if (val != other) {
            val = other;
            frames = 0;
        }
    }

    void process() override {
        if (frames) {
            val += target_change_per_frame;
            frames--;
            if (!frames) {
                val = target_val;
            }
        }
    }
    
    void set_target_val(T target_val, unsigned int frames) {
        if (target_val == this->target_val) return;
        this->target_val = target_val;
        target_change_per_frame = target_val - val;
        target_change_per_frame /= frames;
        this->frames = frames;
    }

    void set_val(const T& val) {
        this->val = val;
    }

    T get_val() const {
        return val;
    }

    T* get_val_addr() const {
        return &val;
    }

    T get_target_change_per_frame() const {
        return target_change_per_frame;
    }

    unsigned int get_frames() const {
        return frames;
    }
private:
    T val{};
    T target_val{};
    T target_change_per_frame{};
    unsigned int frames = 0;
};

此类在我的项目中的主要用途之一是使用

TargetVar<glm::vec3>
来处理纹理的位置。因此,通常将
TargetVar<T>
T
进行比较(例如,将纹理的位置与屏幕上的位置进行比较,即
TargetVar<glm::vec3>
glm::vec3
),但比较
 也很常见TargetVar<T>
与另一个
TargetVar<T>
(例如,将一个纹理的位置与另一个纹理的位置进行比较,即
TargetVar<glm::vec3>
TargetVar<glm::vec3>
)。为了使这更方便,我向
TargetVar
类添加了以下运算符重载:

    template <typename U>
    TargetVar<T>& operator=(const U& rhs) {
        val = (T)rhs;
        frames = 0;
        return *this;
    }

    template <typename U>
    bool operator==(const U& rhs) {
        return val == rhs;
    }

    template <typename U>
    bool operator!=(const U& rhs) {
        return val != rhs;
    }

    template <typename U>
    TargetVar<T>& operator=(const TargetVar<U>& rhs) {
        if (this != &rhs) {
            val = rhs.get_val();
            frames = 0;
        }
        return *this;
    }

    template <typename U>
    bool operator==(const TargetVar<U>& rhs) {
        return val == rhs.get_val();
    }

    template <typename U>
    bool operator!=(const TargetVar<U>& rhs) {
        return val != rhs.get_val();
    }

这个系统已经工作了几周,没有任何问题,但我注意到某些比较会导致 VS 中出现错误。例如:

    TargetVar<glm::vec3> tv1 = glm::vec3(0.0);
    TargetVar<glm::vec3> tv2 = glm::vec3(0.0);
    if (tv1 != tv2) {
        /*
            Error E0350 - more than one operator "!=" matches these operands:
            function template "bool TargetVar<T>::operator==(const U &rhs) [with T=glm::vec3]", with reversed arguments
            function template "bool TargetVar<T>::operator==(const TargetVar<U> &rhs) [with T=glm::vec3]", with reversed arguments
            function template "bool TargetVar<T>::operator!=(const U &rhs) [with T=glm::vec3]"
            function template "bool TargetVar<T>::operator!=(const TargetVar<U> &rhs) [with T=glm::vec3]"
            operand types are: TargetVar<glm::vec3> != TargetVar<glm::vec3>
        */
    }
    if (tv1 == tv2) {
        /*
            Error E0350 - more than one operator "==" matches these operands:
            function template "bool TargetVar<T>::operator==(const U &rhs) [with T=glm::vec3]", with reversed arguments
            function template "bool TargetVar<T>::operator==(const TargetVar<U> &rhs) [with T=glm::vec3]", with reversed arguments
            function template "bool TargetVar<T>::operator==(const U &rhs) [with T=glm::vec3]"
            function template "bool TargetVar<T>::operator==(const TargetVar<U> &rhs) [with T=glm::vec3]"
            operand types are: TargetVar<glm::vec3> == TargetVar<glm::vec3>

        */
    }
    if (tv1 != tv2.get_val()) {
        //No errors
    }
    if (tv1 == tv2.get_val()) {
        //No errors
    }
    if (tv1.get_val() != tv2.get_val()) {
        //No errors
    }
    if (tv1.get_val() == tv2.get_val()) {
        //No errors
    }

这些错误实际上并不会阻止程序编译,但我想知道为什么 VS 认为 tv1 到 tv2 的比较有问题,但 tv1 到 tv2.get_val() 比较没有问题。

此外,出于好奇,我删除了 != 运算符重载,以查看“使用反向参数”位是否会消失。它没有改变任何现有的错误,但它确实引入了以下错误,这些错误确实导致程序无法编译:

if (tv1 != tv2) {
    /*
        Error C2666 - 'TargetVar<glm::vec3>::operator ==': overloaded functions have similar conversions
    */
}
if (tv1 == tv2) {
    /*
        Error C2666 - 'TargetVar<glm::vec3>::operator ==': overloaded functions have similar conversions
    */
}

最终,程序按原样运行得很好,但我想知道为什么 VS 只在特定情况下出现问题,以及除了手动将 .get_val() 手动放入所有内容之外,我是否可以做任何事情我的操作。

c++ templates operator-overloading
1个回答
0
投票

所以....

Cxxxx
当您运行构建时,一系列错误来自实际编译器。
Exxxx
错误来自编辑。编辑器对 C++ 代码的解释有时有点奇怪,因为它会努力找出因正在编辑而无效的代码。类成员的主体不再与类本身的声明相匹配,诸如此类。

当编辑器出错时,它会影响“GoTo Definition”等操作,但不会阻止您构建。

编辑器经常出错,因此我通常会从错误列表顶部的下拉列表中关闭来自编辑器的错误/警告消息。

实际上,我什至几乎不使用“错误列表”窗口,更喜欢“输出”窗口的“构建”选项卡,在其中可以看到完整的错误消息,而无需强制进入整洁的 n 列表。

© www.soinside.com 2019 - 2024. All rights reserved.